DSprout is a LAN-based distributed storage project.
It has five main parts:
server/dsprout-satellite: the shared metadata and coordination serviceserver/dsprout-agent: the local control service for one machineserver/dsprout-worker: the storage worker process that stores shards and joins the networkserver/dsprout-uplink: the CLI used for upload, download, and repair flowsapp/: the Next.js dashboard used to control the local machine and inspect the shared network
This README explains how to run DSprout in the two most important roles:
- Machine A: the machine that hosts the shared satellite
- Machine B: another contributor machine that joins Machine A over the same LAN
This guide is intentionally manual and command-first. It does not depend on helper scripts.
Machine A hosts the satellite on port 7070.
Every contributor machine, including Machine B, runs:
- one local agent on
127.0.0.1:7081 - one local worker on port
5901 - one local frontend on port
3000
Important rules:
- Machine B must use Machine A's LAN IP for the satellite URL
- the local agent always stays on
127.0.0.1:7081 - every worker must advertise its own machine's LAN IP
- do not advertise
127.0.0.1,localhost, or0.0.0.0
Install the following on every machine:
- Rust and Cargo
- Node.js and npm
Clone the repository on every machine:
git clone https://github.com/channi23/Dsprout.git
cd DsproutBuild the backend crates once:
cd server
cargo build -p dsprout-common -p dsprout-satellite -p dsprout-worker -p dsprout-uplink -p dsprout-agent
cd ..Install frontend dependencies once:
cd app
npm install
cd ..Run this on each machine:
ipconfig getifaddr en0If en0 is empty, try:
ipconfig getifaddr en1You can also inspect all IPs with:
ifconfig | grep 'inet 'Use the real LAN IP from your current Wi-Fi or Ethernet network.
Examples of good IPs:
192.168.0.10110.145.113.207
Examples of bad IPs for cross-machine access:
127.0.0.1localhost0.0.0.0
7070: satellite7081: local agent5901: worker3000: frontend
If you already have something else using one of these ports, stop that process first or change your local setup before continuing.
Machine A is the machine that hosts the shared satellite.
In the examples below, replace:
<MACHINE_A_IP>with Machine A's LAN IP
Example:
<MACHINE_A_IP>->192.168.0.101
You will use:
- Terminal 1 for the satellite
- Terminal 2 for the local agent
- Terminal 3 for the frontend
In Terminal 1:
cd /path/to/Dsprout/server
cargo run -p dsprout-satelliteExpected result:
- the process stays running
- it listens on
http://0.0.0.0:7070 - other machines should reach it with
http://<MACHINE_A_IP>:7070
Quick check from Machine A:
curl -s http://127.0.0.1:7070/workersIn Terminal 2:
cd /path/to/Dsprout/server
DSPROUT_SATELLITE_URL=http://<MACHINE_A_IP>:7070 cargo run -p dsprout-agentExpected result:
- the process stays running
- it listens on
http://127.0.0.1:7081
Quick check:
curl -s http://127.0.0.1:7081/statusCreate or update app/.env.local:
SATELLITE_URL=http://<MACHINE_A_IP>:7070
LOCAL_AGENT_URL=http://127.0.0.1:7081In Terminal 3:
cd /path/to/Dsprout/app
npm run devOpen:
http://localhost:3000
Open:
http://localhost:3000/agent
Set the worker fields to:
listen_multiaddr=/ip4/0.0.0.0/tcp/5901
advertise_multiaddr=/ip4/<MACHINE_A_IP>/tcp/5901
satellite_url=http://<MACHINE_A_IP>:7070
Then start the worker from the page.
Open:
http://localhost:3000/contributors
Use:
Register from Local Agent
This is the preferred path because it keeps the worker identity consistent with the agent-managed worker.
Check the local agent:
curl -s http://127.0.0.1:7081/statusHealthy values should include:
"running":true"identity_match":true"multiaddr_match":true
Check the satellite worker list:
curl -s http://127.0.0.1:7070/workersCheck the UI:
http://localhost:3000/workers
Machine A should appear there with its LAN IP in multiaddr.
Machine B is another machine on the same LAN.
In the examples below, replace:
<MACHINE_A_IP>with Machine A's LAN IP<MACHINE_B_IP>with Machine B's LAN IP
Example:
<MACHINE_A_IP>->192.168.0.101<MACHINE_B_IP>->192.168.0.115
From Machine B:
curl -s http://<MACHINE_A_IP>:7070/workersIf this fails, do not continue until Machine B can reach Machine A over the network.
You will use:
- Terminal 1 for the local agent
- Terminal 2 for the frontend
- optional Terminal 3 for verification commands
In Terminal 1:
cd /path/to/Dsprout/server
DSPROUT_SATELLITE_URL=http://<MACHINE_A_IP>:7070 cargo run -p dsprout-agentQuick check:
curl -s http://127.0.0.1:7081/statusCreate or update app/.env.local:
SATELLITE_URL=http://<MACHINE_A_IP>:7070
LOCAL_AGENT_URL=http://127.0.0.1:7081In Terminal 2:
cd /path/to/Dsprout/app
npm run devOpen:
http://localhost:3000
Open:
http://localhost:3000/agent
Set:
listen_multiaddr=/ip4/0.0.0.0/tcp/5901
advertise_multiaddr=/ip4/<MACHINE_B_IP>/tcp/5901
satellite_url=http://<MACHINE_A_IP>:7070
Then start the worker.
Open:
http://localhost:3000/contributors
Use:
Register from Local Agent
Check the local agent:
curl -s http://127.0.0.1:7081/statusHealthy values should include:
"running":true"identity_match":true"multiaddr_match":true
From Machine A:
curl -s http://127.0.0.1:7070/workersOr from Machine A's frontend:
http://localhost:3000/workers
Machine B should appear with:
- its own unique worker ID
- its own LAN IP in the
multiaddr - recent
last_seen
If you do not want to configure the worker from the UI, you can do it through the agent API.
Run this on the machine whose worker you want to control:
curl -s -X POST http://127.0.0.1:7081/config \
-H 'content-type: application/json' \
-d '{
"listen_multiaddr": "/ip4/0.0.0.0/tcp/5901",
"advertise_multiaddr": "/ip4/<THIS_MACHINE_IP>/tcp/5901",
"satellite_url": "http://<MACHINE_A_IP>:7070",
"restart_if_running": true
}'curl -s -X POST http://127.0.0.1:7081/start \
-H 'content-type: application/json' \
-d '{}'curl -s -X POST http://127.0.0.1:7081/stop \
-H 'content-type: application/json' \
-d '{}'curl -s http://127.0.0.1:7081/storageFor a new session, use this order:
- Start the satellite on Machine A
- Start the agent on Machine A
- Start the frontend on Machine A
- Start and register Machine A's worker
- Start the agent on Machine B
- Start the frontend on Machine B
- Start and register Machine B's worker
- Check
/workerson Machine A
In the local agent status response:
running=trueidentity_match=truemultiaddr_match=true
In the workers list:
- each machine appears once as an active worker
multiaddrcontains the correct LAN IP for that machinelast_seenstays fresh
In the UI:
/agentshows the local worker as running/workersshows both Machine A and Machine B
Typical causes:
- Machine A satellite is not running
- wrong Machine A IP
- machines are on different Wi-Fi networks
- firewall is blocking port
7070
Check:
curl -s http://<MACHINE_A_IP>:7070/workersTypical causes:
- worker process is not running
- wrong advertise address
- old stale worker record is still in the satellite
- agent started, but worker was never started
Check:
curl -s http://127.0.0.1:7081/statusTypical causes:
- worker was manually registered with the wrong ID
- an older worker identity is still stored in the satellite
- registration was done outside the local agent flow
Preferred fix:
- stop the worker
- start the worker from
/agent - use
Register from Local Agentin/contributors
Bad examples:
/ip4/127.0.0.1/tcp/5901/ip4/0.0.0.0/tcp/5901/dns4/localhost/tcp/5901
Good example:
/ip4/<THIS_MACHINE_IP>/tcp/5901
Check satellite:
curl -s http://127.0.0.1:7070/workersCheck local agent:
curl -s http://127.0.0.1:7081/statusRun frontend:
cd app
npm run devRun satellite:
cd server
cargo run -p dsprout-satelliteRun agent:
cd server
DSPROUT_SATELLITE_URL=http://<MACHINE_A_IP>:7070 cargo run -p dsprout-agentIf you started services manually in terminals, stop them with Ctrl+C in the terminals where they are running.
If you want a clean shutdown order:
- Stop the frontend
- Stop the local agent
- Stop the satellite
Stopping the worker through the agent before shutting down is also fine:
curl -s -X POST http://127.0.0.1:7081/stop \
-H 'content-type: application/json' \
-d '{}'The main rule is simple:
- Machine A hosts the satellite
- every other machine points to Machine A's LAN IP for
SATELLITE_URL - every worker advertises its own LAN IP
- the local agent always remains on
127.0.0.1:7081
If you keep those four rules correct, Machine A and Machine B setup is usually straightforward.