Mesh walkthrough: borrow another machine's GPU
Two ways to use someone else's GPU, which one you want, and the exact steps for each.
How to run a model using the GPU of another machine — including when the two are in different buildings.
Every step says what it does and what you should see. If the expected output does not appear, stop there: each step fails for a different reason, and carrying on only makes the diagnosis harder.
First: which of the two do you want?
Genesi can borrow another machine's GPU in two completely different ways. Almost everyone wants the first one.
| Serve (Turbo over HTTP) | Pool (VRAM over RPC) | |
|---|---|---|
| Command | genesi-mesh serve on | genesi-mesh worker on |
| What crosses the network | Text | Layer activations, every token |
| Use it when | The model fits on the GPU machine | The model fits on neither machine alone |
| Speed | Network barely matters | Bounded by round-trip latency |
| Runs the model | The GPU machine | Split across both |
If the model fits on the machine with the GPU, use Serve. Pooling that same model is dramatically slower, and not by a little.
Measured on a real two-machine setup: a 1.9 GB model, client in a VM with no GPU, worker on an RTX 3050 with 6.7 GB free, over a direct LAN link. Pooling worked exactly as designed — the weights landed on the remote GPU. The GPU then sat at 2–3% utilisation, idle, waiting on a 9 ms round trip, while roughly 1.2 MB/s of tensor traffic bought almost no work. The bottleneck is the round trip, and no amount of tuning moves it.
Pooling earns its keep for one thing only: running a model that otherwise could not run at all.
Which machine is which
| The GPU machine | The other one | |
|---|---|---|
| In Serve mode | Runs the model and serves the API | Just a client; talks HTTP |
| In Pool mode (worker) | Lends its VRAM, runs rpc-server | Holds the model, runs llama-server |
| Needs a GPU | Yes | No |
The GPU machine cannot be a virtual machine. A VM does not have the host's GPU. The other machine can be a VM — it needs no GPU at all.
Prerequisites (both modes)
Install a llama.cpp with the RPC backend on each machine — CUDA on NVIDIA, Vulkan elsewhere. The backends do not have to match; each machine executes on whatever its own build has.
sudo pacman -Syu genesi-llama-cpp-cuda # NVIDIA
sudo pacman -Syu genesi-llama-cpp # AMD / Intel / genericWhat must match is the llama.cpp version. Both packages are pinned to one upstream commit for exactly this reason: two machines on different builds hang forever at "loading model" with nothing printed on either end. Mesh now refuses such a pairing outright rather than letting it hang. Update both machines together.
Check each machine:
genesi-mesh doctordoctor probes the live system, not just the config: whether the ports are
actually listening, and whether a firewall is dropping them. It distinguishes
refused (reachable, nothing listening — start the service) from blocked
(no answer at all — open the port), which is the difference between two very
different afternoons.
Mode A — Serve (recommended)
The GPU machine runs the model; the other one just talks to it.
On the GPU machine, start serving
sudo genesi-mesh serve onWhat it does: points Turbo at the network instead of loopback, opens port
11435 under whichever firewall is actually running, and enables the service.
All three, reporting each — doing them by hand is three steps that are each easy
to half-do.
Expected: confirmation of each step. If it says it found no active firewall
manager, that is information, not a failure: a rule written to a stopped ufw
prints "Rules updated", exits 0 and filters nothing.
Turbo has no authentication. Leaving loopback is a deliberate decision; only do it on a network you control.
Pair the machines
Follow Pairing below, then come back.
On the other machine, just use it
genesi-ai-turbo serve llama3.2:3bThere is nothing to configure. The mesh advertises which peers are serving Turbo, and a machine with no usable GPU automatically uses a peer's rather than building a CPU server next to an idle remote GPU. It prints which one it picked.
Force a local server anyway with --local (or GENESI_TURBO_LOCAL=1).
Confirm
genesi-mesh peersA peer serving Turbo is tagged [turbo: <model>], naming what it is running.
By default each machine picks the best Turbo available. To decide for yourself:
genesi-mesh use # what is selected, and what is in effect
sudo genesi-mesh use local # always run here
sudo genesi-mesh use old-pc # pin one machineA pinned peer that stops serving falls back to this machine, not to another peer, and switches back on its own when it returns.
Mode B — Pool VRAM
Only when the model fits on neither machine alone.
On the GPU machine, prove it can lend before involving the network
sudo systemctl enable --now genesi-meshd
genesi-mesh selftestWhat it does: starts a real rpc-server and connects a real client to it,
entirely within this one machine.
Expected: PASS — this machine can serve its GPU to the mesh.
A failure here is local — driver or build. Fix it before adding a second machine.
Start lending VRAM
sudo genesi-mesh worker onExpected: genesi-mesh status shows worker: ON (listening on ...).
Verify it is really listening — the config saying "on" is not proof the process started:
ss -tlnp | grep 50052rpc-server has no authentication either. worker on moves the bind off
loopback; restrict it to your VPN by setting rpc_bind = <your-vpn-ip> in
/etc/genesi-mesh/mesh.conf, then sudo systemctl reload genesi-meshd.
Pair, then run
After Pairing:
genesi-ai-turbo serveExpected: [mesh] pooling across: <address>:50052.
If pooling is not used, Turbo now says why — no peers, no --rpc support,
too big even pooled, or the model already fits locally. Silence used to be the
only answer, which was indistinguishable from the feature not existing.
Mesh pools against free VRAM, not the size of the card. A worker busy running its own model on the very GPU it is lending has almost nothing to give, and announcing capacity instead of availability made loads fail at allocation time after transferring everything.
Confirm the remote GPU is working
On the GPU machine, while the other one generates:
watch -n1 nvidia-smiThe AI Mode Monitor's Mesh tab also states plainly whether Turbo is currently using the mesh or running locally.
Pairing
Needed by both modes.
Put both machines on one network
sudo pacman -S tailscale
sudo systemctl enable --now tailscaled
sudo tailscale up
tailscale ip -4Skip if both machines are already on one router. Sign in with the same account on both, and note each address.
Mandatory checkpoint, from one machine:
ping <the-other-address>If this does not answer, stop. Nothing below fixes an unreachable machine.
Create the trusted network
On the first machine:
sudo genesi-mesh initCopy the secret it prints. On the second:
sudo genesi-mesh join <the-secret>Both machines end up with an identical secret. That is the goal, not a bug — a shared secret is how the two ends authenticate each other.
Register the address (required on a VPN)
sudo genesi-mesh peer <the-other-address>On both machines, each pointing at the other.
What it does: discovery uses UDP multicast, which no VPN forwards. This sends the announcement straight to the address by unicast, which every VPN carries.
Without this, genesi-mesh peers stays empty forever on a VPN. It is the most
common way a correct setup looks broken. On a shared LAN it is unnecessary.
Confirm
genesi-mesh peersPeers (1)
genesi-x8664 100.64.162.89 CUDA 6871 free of 8192 MiB worker [turbo: llama3.2:3b]If the peer appears, you are paired. If not, fix it here.
All of this is also available without a terminal, in the Mesh tab of the AI Mode Monitor: the sharing toggles, registering a machine by address, create/join, and the doctor.
Where it usually gets stuck
| Symptom | Cause | Fix |
|---|---|---|
rpc-server: missing | llama.cpp without GGML_RPC=ON | Install genesi-llama-cpp or -cuda |
selftest fails | Local driver or build problem | Fix before involving the network |
| Hangs at "loading model" | Mismatched llama.cpp versions | Update both machines |
peers empty on a VPN | Multicast does not cross it | genesi-mesh peer <ip> on both |
peers empty on one LAN | Firewall | genesi-mesh doctor names the zone |
| Connects, then fails to allocate | The worker's GPU is busy | Free it, or pick a smaller model |
| Pooling works but is very slow | Round-trip bound — expected | Use Serve instead if the model fits |
| A command seems to hang | You ran genesi-meshd (the daemon) | Use genesi-mesh, without the d |