One network.
One machine.
Pool every device you own into a single, latency-aware computer
Live demonstration
octo, measuring its own legs
A snapshot of octo nodes and octo pairs from the rig this was built on: a Windows gaming PC (through WSL) and two Orange Pi 5B boards. Sample data from a real run, not your network.
Legs
- ✓ sealed heartbeat from d4a3988d — 0.4 ms off schedule
- ● peers to measure: b671690d, fee5d6e2
- ✕ refused: not an octo message (empty 404)
- ✓ pairs updated, matrix saved
Round trips between legs
| PC | aghome2 | ubuntu | |
|---|---|---|---|
| PC | · | 5.85 ms far | 4.93 ms near |
| aghome2 | 5.85 ms far | · | 0.95 ms fast |
| ubuntu | 4.93 ms near | 0.95 ms fast | · |
- fast ≤ 1 ms · near ≤ 5 ms · far > 5 ms
- every pair measured by both ends, smoothed on the head
Secure by default
Ink does two jobs.
Every message octo sends is sealed with ChaCha20-Poly1305. To anyone else on the network, the head looks like nothing at all.
It protects
Secrets never cross the network. The join code, the admin key and each device's key only ever seal messages; they are never sent. A tampered message, a replay against another command, or one older than 60 seconds is rejected.
It hides
Anything that isn't a sealed octo message gets an empty 404. Probes between legs that don't carry a current pair token get no answer at all. Device ids are random, so they reveal no hostnames.
It marks
Every leg carries an ink mark, a short public fingerprint of its key, shown in octo nodes. octo labels --apply inks your k3s cluster with each node's job, tier and mark. octo remove deletes a key for good.
Legs
Which device does what.
octo works out each leg's jobs from its hardware, how close it is, and how often it's on. The first job listed is the leg's main job.
| Job | When | Good for |
|---|---|---|
| gpu | the OS can use a GPU | AI models, rendering, video encoding |
| npu | has an AI chip (Orange Pi 5B) | small, efficient AI models |
| compute | 8+ threads and within 5 ms | builds, containers, game servers |
| service | on 90%+ of the time, no GPU, within 5 ms | always-on services, the head |
| background | over 5 ms away | backups, jobs that can wait |
| general | none of the above | light general work |
On a typical rig: gaming PC gpu, compute · Orange Pi 5B npu, compute, service · Pi 5 service. octo pool adds every approved, online leg into one machine; octo place ranks legs for a job by spare capacity minus a distance penalty.
The head
Where it is, and what happens if it dies.
Always on, never the gaming PC
octo head shows where the head is, which device it runs on, its standbys, and a ranking of which device would make the best head. The ranking favors always-on, close, low-power boards and avoids the GPU machine, since it's loaded and rebooted for games.
A standby takes over in 30 seconds
Run a standby on a second device. It copies the head every 5 seconds. If the head goes quiet for 30 seconds the standby takes over and bumps the epoch; the legs follow it automatically. If the old head comes back, it sees the newer epoch and steps down, so there are never two heads.
Latency
Measured to the head, and between legs.
Each leg times 5 sealed round trips to the head every check-in. Since 0.4, the legs also measure each other: the head hands every leg a short peer list and a pair token, each leg answers sealed UDP probes on port 7701, and once a minute times its peers. The head keeps one smoothed, symmetric matrix.
fast · 1 ms or less
Wired and close. Interactive services, build workers.
near · up to 5 ms
Typical Wi-Fi. Game servers, AI inference, caches.
far · over 5 ms
Or not measured yet. Background jobs only.
rig-brain integration
When the rig is gaming, octo gets out of the way.
A leg that runs next to rig-brain carries its profile in every check-in. While that profile is gaming:
rig: gaming (heavy work is kept off this leg).Install
Three services, one join code.
Build on each device with cargo build --release and install the single octo binary. Then:
Head (the always-on board)
The brain prints a join code for devices and an admin key for you.
# /etc/octo/brain.env OCTO_ADVERTISE=http://PI_IP:7700 sudo systemctl enable --now octo-brain sudo cat /var/lib/octo/brain.json # join_code and admin_key
Standby (a second board)
Copies the head and takes over if it goes quiet.
# /etc/octo/standby.env OCTO_ADVERTISE=http://OPI_IP:7700 OCTO_HEAD=http://PI_IP:7700 OCTO_KEY=ADMIN_KEY sudo systemctl enable --now octo-standby
Every leg
Joins with the join code only. It does nothing for the pool until you approve it.
# /etc/octo/agent.env OCTO_BRAIN=http://PI_IP:7700 OCTO_CODE=JOIN_CODE sudo systemctl enable --now octo-agent # open udp/7701 from the LAN for leg-to-leg latency
Run it
From anywhere on the LAN with the admin key.
octo nodes # every leg: job, ink mark, latency, body octo approve 696ca262 # let a pending device in octo head # where the head is, and the best candidates octo pool # the whole octopus as one machine octo pairs # round trips between every pair of legs octo place --gpu --max-tier fast # best GPU leg within 1 ms octo labels --apply # ink the k3s cluster
Keep port 7700 and udp/7701 on your home network; never forward them to the internet. All devices need roughly correct clocks. Brains keep /var/lib/octo/brain.json at mode 600: it holds every key.
Roadmap
Where octo is going.
done v0.3
Latency between every pair of legs, not just to the head. Bandwidth per pair is still to do.
next v0.4
A phone page on the head with approve buttons. The console covers approving and remote installs; the per-leg page is still to do.
done v0.5
rig-brain tells octo when you're gaming, and octo moves heavy jobs off the rig.