Closed bug report

Mesh relay never connects: local relay proxy reports 'Failed to connect to relay server' (relayConnected=false), peers unreachable

Colby Knox · 1mo ago ·closed by John Lauer

ab 2.1.170 on both boxes (Colby-ROG2, DESKTOP-BAR6S0F) · Windows · mesh phase P1, mode relay

What I did

Tried to add DESKTOP-BAR6S0F to the mesh from Colby-ROG2. The peer is in the account directory and already trusted (how: first-start). Then I restarted ab on Colby-ROG2 with the restart verb to re-establish the relay.

Expected

relayConnected: true, and --target DESKTOP-BAR6S0F reaching the peer over the mesh (through the relay, because neither box publishes direct endpoints).

What happened

The local relay proxy never connects to the relay, either before or after the restart:

"relay": "<default Adom mesh relay>",
"currentRelay": "http://127.0.0.1:56462/",
"relayConnected": false,
"relayUpstreamStatus": 200,
"relayShim": { "running": true, "forwarded": 746, "failed": 44 },   // 26 s after restart: forwarded 10, failed 2
"relayStatus": [{ "connected": false, "lastError": "Failed to connect to relay server", "url": "http://127.0.0.1:56462/" }],
"endpoints": [],
"peerCount": 1

desktop_mesh_peers shows DESKTOP-BAR6S0F with connected: false, endpoints: [], path: null. --target DESKTOP-BAR6S0F <verb> returns target_not_found, and the hc relay lists only Colby-ROG2.

From a container, the relay's base URL returns HTTP 200, and /relay returns 400 to a plain GET. The relay is up, so the failure looks like the iroh relay upgrade through the local proxy at 127.0.0.1. That's my guess and I haven't confirmed it.

Side notes

  • Both boxes publish endpoints: [], so even same-LAN direct dialling has nothing to use. Is that expected in relay mode?
  • desktop_mesh_trust {"action":"raise","name":"DESKTOP-BAR6S0F"} returned bad_args: nodeId (or name), or all:true, required while the peer directory was still empty. The peer only appeared after desktop_mesh_peers {"refresh":true}. The error should say "unknown peer name; try desktop_mesh_peers refresh:true" instead of implying the arg is missing.

6 Replies

John Lauer · 1mo ago

Found the cause: it is enrolment, not the local proxy.

The Adom mesh relay admits only enrolled accounts. Each account's token lives in its cloud settings (bridge.mesh.relayToken), every ab of that account presents it on the WebSocket upgrade, and the relay checks it against its access.shared_token list. That list currently holds exactly one account's token. Any other account's boxes are turned away, which iroh reports as the generic "Failed to connect to relay server". Your two boxes' desktop_mesh_status should show relayAuth: "none".

So relay-mode mesh, which ships on by default, works today only for the one enrolled account. How other accounts get enrolled (one shared token for every ab, or per-account enrolment) is a decision I've asked John to make. This issue stays open until that lands.

What changed in 2.1.171:

  • desktop_mesh_status carries relayNote whenever the relay is not connected. With no token it says: "this account has no relay token ... the relay admits only enrolled accounts". A token the relay rejects (401/403) and a plain connection failure each get their own wording.
  • Side note fixed: desktop_mesh_trust {action:"raise", name:"..."} with a name the directory doesn't know answers errorCode: unknown_peer with "run desktop_mesh_peers {refresh:true} and retry". It no longer implies the argument is missing.

endpoints: [] is expected in relay mode: relay mode binds only loopback and advertises no addresses (that is what keeps it firewall-dialog-free). Same-LAN direct dialling needs mesh_mode: "direct".

John Lauer · 1mo ago

Fixed for every account in 2.1.172 (insiders now). John chose per-account sign-up, and it's live.

How admission works now:

  • The Adom mesh relay admits individual machines. For each machine that connects, it asks a small sign-up service on the same container whether that machine is enrolled. There is no longer a single shared token.
  • Adom Bridge 2.1.172 signs its machine up automatically whenever the box is signed in to Adom: on mesh start, once a day, and whenever the relay refuses it.
  • The sign-up request proves two things:
    1. The machine owns its node id: an ed25519 signature made with the machine's own node key.
    2. It belongs to a live Adom account: the user's session, which the service checks once against Carbon and never stores.
  • Mesh traffic itself is unchanged: end-to-end encrypted between the two machines. The relay only forwards ciphertext.

Checked live (2026-10-08):

  • arav-rog on 2.1.172 signed itself up on mesh start: relayEnrollment: {state: "enrolled", ok: true}. The service log shows the signature and the account check passing.
  • The relay was then switched to per-machine admission. The existing fleet reconnected, and verbs to arav-rog, ConfRoomROG and winvm all routed over the mesh (32-100 ms).
  • Machines that are not enrolled are refused. The relay's log shows exactly that for four node ids, which are probably your two boxes and their old keys.

For Colby-ROG2 and DESKTOP-BAR6S0F: update to 2.1.172 (insiders) while signed in to Adom. Within a few seconds of the mesh starting, desktop_mesh_status should show relayEnrollment.ok: true and relayConnected: true, and --target DESKTOP-BAR6S0F should route over the mesh. If either shows ok: false, its error says why. Please confirm here and I'll close.

Colby Knox · 1mo ago

I updated both boxes to 2.1.172 while signed in. Enrolment worked, but the relay still doesn't connect after more than 2 minutes.

Both boxes report the same (Colby-ROG2 and DESKTOP-BAR6S0F):

relayEnrollment: { state: "enrolled", ok: true, trigger: "mesh start" }
relayConnected: false
relayAuth: "none"
relayStatus: [{ connected: false, lastError: "Failed to connect to relay server", url: "http://127.0.0.1:<shim port>/" }]
relayShim: Colby-ROG2 { failed: 4, forwarded: 17 }, DESKTOP-BAR6S0F { failed: 0, forwarded: 19 }
uptimeSec: ~128

relayAuth still says "none" after a successful enrolment. Is that expected under per-machine admission, or is the shim not using the enrolment?

These boxes run in mesh_mode: "direct". I switched them earlier as a workaround because they share a LAN. Both still list the relay in status. If the relay path is only exercised in relay mode, tell me and I'll flip one box back to test.

The mesh itself works: --target DESKTOP-BAR6S0F status returns route.via: "mesh" at 23 ms, direct over the LAN. The relay is the only part that isn't connecting.

John Lauer · 1mo ago

Thanks, that was a bug in the sign-up service, not in your boxes. It's fixed (server-side only, no ab update needed).

What happened: after saving a sign-up, the service updated the list on disk but kept answering the relay from its old in-memory copy. So COLBY-ROG2 was enrolled and still refused. Worse, the next sign-up wrote over the previous one, which dropped DESKTOP-BAR6S0F from the list. The relay's log showed exactly that: access DENIED 8aff88e6754b (COLBY-ROG2) after its successful enrolment.

Fix: the in-memory list now moves with the file. Checked on the service: COLBY-ROG2 answers true now, and a fresh throwaway enrolment is admitted at once without a restart (then deleted, and refused at once).

What you need to do: nothing, or restart ab on DESKTOP-BAR6S0F to hurry it.

  • COLBY-ROG2 should connect within moments.
  • DESKTOP-BAR6S0F signs up again by itself the next time the relay refuses it, at most 10 minutes after its last attempt.
  • After that, relayEnrollment.ok: true with relayConnected: true on both.

Your questions:

  • relayAuth: "none" is expected. That field reports the old account-wide token, which per-machine admission no longer uses. relayEnrollment is the one that matters now. I'll relabel relayAuth in the next release so it doesn't read as a failure.
  • mesh_mode: "direct" is fine: direct mode uses the LAN and the relay together, and iroh keeps a relay connection for when direct paths fail. No need to flip a box back.
Colby Knox · 1mo ago

Confirmed fixed. Both boxes are on 2.1.172 with relayEnrollment.ok: true and relayConnected: true. COLBY-ROG2 connected on its own after your server fix. DESKTOP-BAR6S0F connected 10 s after an ab restart. --target DESKTOP-BAR6S0F routes via mesh. OK to close. Thanks!

John Lauer · 1mo ago

Thanks for confirming. The relay's list matches: COLBY-ROG2 and DESKTOP-BAR6S0F are both enrolled, and neither has been refused since the fix. Closing. The relayAuth relabel (so it no longer reads 'none' under per-machine admission) goes into the next ab release.

John Lauer closed this · 1mo ago

Log in to reply.