Skip to content

IDEA-Amrita/NodeShare

Repository files navigation

NodeShare

NodeShare lets two computers — anywhere in the world — connect directly and securely, so one machine can run a piece of work (a "task") on the other.

You start NodeShare on a machine that has spare power (the Provider), share a single command with a friend, and they connect from their machine (the Requester). From there you get an interactive terminal where you can:

  • check the connection (ping),
  • inspect the other machine's hardware (sysinfo),
  • send a folder of code to the Provider (create-task), and
  • run that code remotely inside Docker and watch the output live (run-task).

No port forwarding, no accounts, no cloud. It works across different home networks out of the box.


Table of contents

  1. What NodeShare does (in plain English)
  2. Key words you'll see
  3. Prerequisites
  4. Install / build
  5. Quick start: your first remote task in ~5 minutes
  6. The interactive terminal — every command explained
  7. Writing your own task
  8. Command-line reference
  9. Other ways to connect (LAN, self-hosted relay)
  10. What happens under the hood
  11. Security model
  12. Cleanup & reliability
  13. Troubleshooting
  14. Project structure
  15. Protocol stack
  16. License

1. What NodeShare does (in plain English)

Imagine you have a powerful desktop at home, and a friend on the other side of the country has a slow laptop. Your friend has some Python code they want to run, but their laptop can't handle it. With NodeShare:

  1. You run nodeshare start on your desktop. NodeShare prints one command.
  2. You send that command to your friend (Discord, WhatsApp, email — anything).
  3. Your friend pastes the command into their terminal. They're now connected directly to your desktop, over an encrypted link.
  4. Your friend types create-task ./their-code to send the code to your desktop, then run-task to run it. The output streams back to their screen in real time, even though it's actually running on your machine.

There are always two roles:

Role Command What it does
Provider nodeshare start Offers its machine. Receives tasks and runs them in Docker.
Requester nodeshare connect Connects to a Provider and drives it through the interactive terminal.

The Provider is the one doing the heavy lifting. The Requester is the one asking for work to be done.


2. Key words you'll see

You don't need to memorise these, but they'll make everything else clearer.

  • Peer — any machine running NodeShare.
  • Peer ID — a long unique fingerprint for a machine, like 12D3KooWSixUHPAtCHVnbi517roFKaHZceVL4FJdAez5rDcGEadq. It's generated once on first run and stays the same forever after, so a peer is always recognisable.
  • Multiaddress (or "multiaddr") — a full "postal address" for a peer that bundles how to reach it and who it is. Example: /dns4/abc.pinggy.link/tcp/33843/p2p/12D3KooW.... You don't write these by hand — NodeShare prints a ready-to-use one for you.
  • Tunnel (Pinggy) — a free service NodeShare uses to give your machine a public address automatically, so peers on other networks can reach you without any router configuration. NodeShare launches it for you.
  • Task — a folder of code you want to run remotely. It must contain a Makefile and a Dockerfile; the actual program can be in any language (Python, C++, Go, …) — the Dockerfile installs the toolchain and the Makefile builds/runs it (see section 7).
  • Interactive terminal (REPL) — after you connect, you get a nodeshare> prompt where you type commands like ping, sysinfo, create-task, and run-task.

3. Prerequisites

You need… On which machine Why Notes
Go 1.21+ Both (to build) NodeShare is written in Go. (Developed against Go 1.25.) Download Go. Skip if you use a prebuilt binary.
Docker Provider only run-task builds and runs your task inside a container. Get Docker. The Docker daemon must be running.
ssh Both (for the tunnel) NodeShare uses it to open the free Pinggy tunnel. Pre-installed on Linux, macOS, and Windows 10+.
Internet Both To reach each other across networks. A LAN-only mode exists too (see section 9).

Only the Provider needs Docker. The Requester just sends a folder and reads logs — it never runs anything locally.


4. Install / build

First, get the source and move into the project folder:

git clone <this-repo-url>
cd NodeShare

Linux / macOS

make build
# produces ./dist/nodeshare

Windows (PowerShell)

make is usually not available on Windows, so build directly with Go:

go build -o dist/nodeshare.exe ./cmd/nodeshare
# produces .\dist\nodeshare.exe

Check it worked

# Linux / macOS
./dist/nodeshare info

# Windows
.\dist\nodeshare.exe info

You should see your machine's Peer ID and hardware details.

Naming in this guide: examples below write nodeshare for brevity. Substitute ./dist/nodeshare (Linux/macOS) or .\dist\nodeshare.exe (Windows).


5. Quick start: your first remote task in ~5 minutes

This walkthrough uses the bundled example task in examples/hello-task/, which simply prints "Hello World". You can run both sides on the same computer (two terminal windows) to try it out, or on two different computers.

Step 1 — Provider: start NodeShare

On the machine that will do the work, run:

nodeshare start

NodeShare opens a free tunnel and, after ~15 seconds, prints a banner like this:

==================================================
NodeShare Ready
==================================================

Public Address:
  /dns4/pieww-106-200-16-7.run.pinggy-free.link/tcp/33843

Peer ID:
  12D3KooWSixUHPAtCHVnbi517roFKaHZceVL4FJdAez5rDcGEadq

Share ONE of the following commands with your peer:

Linux / macOS:
  ./dist/nodeshare connect /dns4/pieww-106-200-16-7.run.pinggy-free.link/tcp/33843/p2p/12D3KooWSixUHPAtCHVnbi517roFKaHZceVL4FJdAez5rDcGEadq

Windows PowerShell:
  .\dist\nodeshare.exe connect /dns4/pieww-106-200-16-7.run.pinggy-free.link/tcp/33843/p2p/12D3KooWSixUHPAtCHVnbi517roFKaHZceVL4FJdAez5rDcGEadq

==================================================
Type a command, or 'help'. (Ctrl-C to stop)
nodeshare>

The Provider now sits at its own nodeshare> prompt, waiting. Leave it running.

Step 2 — share the command

Copy the line under "Linux / macOS" or "Windows PowerShell" (whichever your peer uses) and send it to them. It already contains the full address and Peer ID — nothing to edit.

Trying it on one computer? Just open a second terminal and use the command yourself.

Step 3 — Requester: connect

In the other terminal (or on your friend's machine), paste the command:

nodeshare connect /dns4/pieww-106-200-16-7.run.pinggy-free.link/tcp/33843/p2p/12D3KooWSixUHPAtCHVnbi517roFKaHZceVL4FJdAez5rDcGEadq

You'll see a summary of the Provider, then an interactive prompt:

── Connected Peer ──────────────────────────────────────
  Peer ID     : 12D3KooWSixUHPAtCHVnbi517roFKaHZceVL4FJdAez5rDcGEadq
  Role        : worker
  Latency     : 212.518ms
  Hostname    : fedora
  OS / Arch   : linux / amd64
  CPU         : Intel(R) Core(TM) Ultra 7 155H (16p / 22l)
  RAM         : 15.10 GB total
  Disk        : 197.91 GB total

Interactive terminal ready. Type 'help' for commands.
nodeshare(…cGEadq)>

Step 4 — try the simple commands

At the nodeshare(...)> prompt, type:

ping

→ shows the round-trip time to the Provider.

sysinfo

→ asks the Provider for its live hardware details and prints them.

help

→ lists every available command.

Step 5 — send a task (create-task)

Send the example folder to the Provider:

create-task examples/hello-task

The path is on the Requester's machine — it's the folder being sent.

Output:

Sending task folder "examples/hello-task" …
✓ received 3 file(s) into /tmp/nodeshare/tasks/task-20260607-083028-b6c8cd4b
  task id: task-20260607-083028-b6c8cd4b  (run it with 'run-task')

The three files (Makefile, Dockerfile, main.py) are now on the Provider. Nothing has executed yet — this step only transfers files.

Step 6 — run it (run-task)

run-task

The Provider builds a Docker image and runs it. The build and program output stream back to your screen live, each line prefixed with [REMOTE]:

Running task task-20260607-083028-b6c8cd4b on the remote peer …
[REMOTE] Building image nodeshare-task-20260607-083028-b6c8cd4b …
[REMOTE] Step 1/5 : FROM python:3.12-slim
[REMOTE] ...
[REMOTE] Successfully tagged nodeshare-task-20260607-083028-b6c8cd4b:latest
[REMOTE] Running container (make) …
[REMOTE] python main.py
[REMOTE] Hello World from a NodeShare remote task!
✓ Task completed successfully

You just ran code on another machine and watched it happen in real time.

Step 7 — finish

Type quit (or exit) on the Requester to disconnect. On the Provider, type quit or press Ctrl-C to stop. When the Requester leaves, the Provider automatically deletes the task files and the Docker image it built — no leftovers.


6. The interactive terminal — every command explained

After connecting, both sides have a prompt. They have different command sets because they play different roles.

Requester commands (the nodeshare(...)> prompt after connect)

Command What it does
ping Measures and prints the round-trip latency to the Provider.
sysinfo Requests the Provider's current hardware/OS details and prints them.
create-task <dir> Validates the folder <dir> and transfers all its files to the Provider. No execution.
run-task [id] Tells the Provider to build & run a transferred task in Docker, streaming logs back live. With no id, it runs the most recently created task.
help (or ?) Lists these commands.
clear Clears the screen.
quit / exit Closes the connection and exits.

Tip: press Tab to auto-complete command names.

Provider commands (the nodeshare> prompt after start)

The Provider mostly serves the Requester, but it has a few local commands:

Command What it does
peers Lists peers currently connected to this Provider.
info / sysinfo Shows this machine's own system information.
help (or ?) Lists these commands.
clear Clears the screen.
quit / exit Stops the daemon and exits.

While the Provider sits at its prompt, it also prints a box whenever a peer connects or a task is received, so you can see activity at a glance.


7. Writing your own task

A task is just a folder. To be valid it must contain:

File Purpose
Dockerfile Describes the container image your code runs in (base image, dependencies, files).
Makefile Defines what make runs. The Provider runs make inside the container.

If either is missing, create-task refuses to send the folder and tells you what's wrong. Everything else is up to you: your program can be in any language, and you can include as many source files, data files, etc. as you like — the whole folder is transferred. NodeShare never inspects your source; it only runs docker build then make.

How the pieces fit together

When you run run-task, the Provider does exactly two things:

docker build -t <image> <your-task-folder>     # 1. build the image
docker run --rm <image> make                   # 2. run `make` inside it

So your Dockerfile must produce an image where running make works — that means make and Python must be installed, and your files copied in.

The bundled example (examples/hello-task/)

main.py

print("Hello World from a NodeShare remote task!")

Makefile (the indented line must start with a real Tab, not spaces)

.PHONY: run

run:
	python main.py

Dockerfile

FROM python:3.12-slim

RUN apt-get update \
    && apt-get install -y --no-install-recommends make \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY . /app

# Default command runs the Makefile's first target.
CMD ["make"]

Walking through it:

  1. FROM python:3.12-slim — start from a small image that already has Python.
  2. RUN apt-get … make — install make (the slim image doesn't ship it).
  3. WORKDIR /app + COPY . /app — put your task files inside the image.
  4. make runs the run: target → python main.py → prints the message.

To make your own task, copy this folder, swap main.py for your code, and adjust the Makefile/Dockerfile (e.g. pip install your dependencies).

A non-Python example (C++)

Nothing about NodeShare is Python-specific — it only runs docker build then make. To run C++ instead, the folder just needs a Dockerfile with a C++ toolchain and a Makefile that compiles and runs your program:

main.cpp

#include <iostream>
int main() { std::cout << "Hello World from a C++ NodeShare task!\n"; }

Makefile (recipe lines indented with a real Tab)

.PHONY: run

run:
	g++ -O2 -o app main.cpp
	./app

Dockerfile (the official gcc image already ships g++ and make)

FROM gcc:13
WORKDIR /app
COPY . /app
CMD ["make"]

The same pattern works for Go, Rust, Node.js, etc. — pick a base image with the right toolchain and have the Makefile build and run your program.


8. Command-line reference

NodeShare is a Cobra-based CLI. These are the top-level commands you run from your shell. (create-task/run-task/ping/sysinfo inside the interactive terminal are covered in section 6.)

Command Description
nodeshare start Start the Provider. Opens a tunnel, prints a connect command, opens a prompt.
nodeshare connect <addr> Connect to a Provider and open the interactive terminal.
nodeshare peers List peers currently connected to this machine.
nodeshare ping <peerID> Send 5 pings to a connected peer and report RTT statistics.
nodeshare info Print this machine's Peer ID, system info, and listen addresses.
nodeshare relay Run a standalone relay node others can bounce through (advanced).

Flags

Flag Used with Meaning
--port all TCP/QUIC listen port (default 4001; connect uses a random free port).
--role start, connect A label for this node, e.g. worker (default) or coordinator.
--log-level all Log verbosity: debug, info (default), warn, error.
--disable-pinggy start Don't open the auto tunnel; show local LAN addresses instead.
--announce-addr start, relay Extra address to advertise (e.g. a manual port-forward). Repeatable.
--no-relay start Disable relay/hole-punching (local-only mode).
--bootstrap start Use a custom relay/bootstrap peer instead of the public defaults.

9. Other ways to connect (LAN, self-hosted relay)

Same network (LAN) — no tunnel needed

If both machines are on the same Wi‑Fi/LAN, skip the tunnel for speed:

# Provider:
nodeshare start --disable-pinggy
# It prints local addresses like /ip4/192.168.1.25/tcp/4001/p2p/<PEER_ID>

# Requester:
nodeshare connect /ip4/192.168.1.25/tcp/4001/p2p/<PEER_ID>

Self-hosted relay (advanced)

If you have a machine with a public IP (a VPS, or a home machine with port 4001 forwarded), you can run your own relay instead of the public defaults:

# On the public machine:
nodeshare relay
# Prints:  /ip4/203.0.113.10/tcp/4001/p2p/<RELAY_PEER_ID>

# Both peers then start with --bootstrap:
nodeshare start --bootstrap /ip4/203.0.113.10/tcp/4001/p2p/<RELAY_PEER_ID>

10. What happens under the hood

 Requester                                   Provider
 (nodeshare connect)                         (nodeshare start)
        │                                          │
        │  1. dial + Noise-encrypted handshake     │
        │─────────────────────────────────────────▶│
        │  2. exchange system info + ping/pong      │
        │◀────────────────────────────────────────▶│
        │                                          │
        │  ===== interactive terminal opens =====   │
        │                                          │
        │  create-task:  manifest + file chunks ──▶ │  saves to
        │                ◀── "received" ack          │  /tmp/nodeshare/tasks/<id>/
        │                                          │
        │  run-task:     "run-task <id>"  ────────▶ │  docker build …
        │                ◀── [REMOTE] log lines ──   │  docker run --rm … make
        │                ◀── TaskCompletion ──────   │  (streams every line live)
        │                                          │
        │  quit / disconnect ─────────────────────▶ │  cleans up files + image
  • Transport & encryption: built on go-libp2p. All traffic is encrypted (Noise) and multiplexed (Yamux) over TCP or QUIC.
  • NAT traversal: UPnP/NAT‑PMP, public Circuit Relay v2, and DCUtR hole punching let two home networks connect without port forwarding. The Pinggy tunnel is an additional zero-config path.
  • Messages: every message is a length-prefixed Protobuf Envelope (handshake, sysinfo, ping/pong, terminal commands, task transfer, file chunks, log updates, task completion).

11. Security model

NodeShare is designed for running tasks with people you trust. Be aware:

  • All traffic is encrypted end-to-end (Noise). Peers are identified by a cryptographic Peer ID.
  • File transfers are sandboxed to a task folder. The Provider rejects any file path that tries to escape its task directory (no ../ tricks) and any file not listed in the transfer manifest.
  • Tasks run inside Docker, isolated from the host, and are cleaned up after.
  • Running a task executes the Requester's code on the Provider. Only accept tasks from people you trust — a Dockerfile can do anything Docker can do.
  • The Provider's address is public while the tunnel is open. The Peer ID in the connect command acts as the shared secret; only share it with your peer.

12. Cleanup & reliability

NodeShare tries hard not to leave a mess on the Provider:

  • When the Requester disconnects (clean quit or a dropped connection), the Provider deletes the transferred task folders and removes the Docker images it built for that session.
  • Containers run with docker run --rm, so they self-remove on exit.
  • If the Requester vanishes mid-run, a watchdog on the Provider notices the dropped connection and force-removes the running container, so no "zombie" container keeps consuming resources.
  • A failed task is reported back as a clear status (e.g. "Docker build failed") rather than silently hanging — and the session stays alive so you can retry.

13. Troubleshooting

"[tunnel] could not be opened" / the public banner never appears (Provider). The free Pinggy tunnel couldn't start within ~45 seconds — usually a firewall blocking the SSH connection, ssh missing from PATH, or a temporary Pinggy hiccup. This is an external-network issue, not a NodeShare bug. When it happens, NodeShare automatically prints ready-to-paste nodeshare connect commands for your local/LAN addresses, so peers on the same network can still connect immediately. For peers on a different network you can:

  • simply re-run nodeshare start to retry the tunnel (it's often transient),
  • skip the tunnel entirely with --disable-pinggy (LAN use), or
  • open the tunnel manually and advertise it: ssh -4 -p 443 -R0:localhost:4001 tcp@a.pinggy.io, then start with --announce-addr /dns4/<host>/tcp/<port>.

"tunnel unavailable" on Windows. Enable the OpenSSH client: Settings → Optional features → OpenSSH Client (ships with Windows 10+).

run-task fails with "Docker build failed" or a Docker connection error. Make sure Docker is installed and the Docker daemon/Docker Desktop is running on the Provider. Test with docker run --rm hello-world.

create-task says my folder is invalid. The folder must contain a Makefile and a Dockerfile (the program itself can be any language). Check the names and that you pointed at the right folder.

make: *** missing separator inside the container. Your Makefile recipe lines must be indented with a real Tab, not spaces.

Connections only work on the same network. Confirm relay is enabled (it is by default — don't pass --no-relay) and that both machines have internet access.

The tunnel expires after ~60 minutes. The free Pinggy tunnel is time-limited. Re-run nodeshare start to get a fresh address and a new connect command.

The interactive prompt looks garbled / doesn't accept typed commands. The interactive terminal needs a real terminal (TTY). Run NodeShare directly in a terminal window — not through a pipe or a non-interactive wrapper.


14. Project structure

Path Responsibility
cmd/nodeshare/ CLI entry point, Cobra commands, and the interactive REPLs.
internal/config/ Runtime configuration, defaults, and the bootstrap relay list.
internal/host/ libp2p host construction, NAT/relay options, and identity persistence.
internal/tunnel/ Pinggy SSH tunnel lifecycle — launch, parse, and address injection.
internal/node/ Connection lifecycle, interactive session, task transfer & execution.
internal/protocol/ Wire framing, the Protobuf message dispatcher, and message handlers.
internal/store/ In-memory, thread-safe peer registry.
internal/sysinfo/ Hardware and OS telemetry collection.
internal/task/ Task-folder validation, file listing, IDs, and safe path handling.
proto/ Protobuf message definitions.
gen/ Generated Go bindings (regenerated via make proto).
examples/hello-task/ A ready-to-run Python example task that prints "Hello World".
examples/hello-cpp/ The same example written in C++ (gcc image).
examples/hello-go/ The same example written in Go (golang image).

15. Protocol stack

NodeShare speaks the standard libp2p protocol suite, so it interoperates cleanly across operating systems and network conditions.

Layer Technology
Transports TCP, QUIC-v1
Security Noise
Multiplexing Yamux
Identity Persistent Ed25519 keypair
NAT traversal UPnP / NAT-PMP, Circuit Relay v2, DCUtR
Messaging Length-prefixed Protobuf Envelope

Build targets (Makefile)

make build    # compile the binary into dist/
make test     # run the unit test suite
make proto    # regenerate Go bindings from proto/*.proto
make cross    # build release binaries for all supported platforms
make help     # list every target

Regenerating Protobuf bindings (make proto) needs protoc and protoc-gen-go. Pre-generated bindings are committed, so a normal build does not require them.


16. License

See the repository for license details.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors