eleven / ocho Public

Clone
git clone https://amadan.net/eleven/ocho

Plain git — no account needed to clone.

Download

Download this file

πŸ€– Relay mode β€” self-hosting with zero routing

lchat relay is the permanent sibling of lchat try (issue #738, Phase 1): your instance runs on your own machine, dials out, and keeps a stable public hostname β€” no port forward, no domain, no DNS, no certificate, no root. Ships dormant: it only works against a gateway that offers a relay domain, and the fleet gateway doesn't yet.

lchat relay                 # run a space from ./lchat-relay.db, keep it relayed
lchat relay --local 127.0.0.1:1747   # relay an instance you already run

What makes a relay different from a trial

| | lchat try | lchat relay | |---|---|---| | Hostname | random, dies with the process | claimed by your keypair, permanent | | Lifetime | 24 hours max | unlimited | | Disconnect | address retires | address sleeps (503) for a grace window, then retires; reconnect revives it | | Reconnect | new address | same address, automatic (backoff ≀ ~32s) | | Admission | 5/IP/hour | same for new claims; reconnects are never rate-limited |

Everything else is identical: the door probe (only Eleven instances), the per-tunnel connection cap, the re-probe every 10 minutes, and the E2EE posture β€” the relay carries the same ciphertext any Eleven server carries.

The identity

On first run the client writes an Ed25519 seed to <db>.relay-id (or lchat-relay.id with --local, or --identity <path>). The file is the hostname: claiming works by signing a gateway nonce, so whoever holds the key holds the name. Back it up; lose it and the name is gone (the gateway operator can free an orphaned claim by deleting its row in the claims db).

Wire shape (internal/tunnel): hello carries mode:"relay"; the gateway answers challenge{nonce}; the client sends claim{pubkey,sig}. A hello without mode is a trial and follows the original flow byte-for-byte, so old clients are unaffected.

Gateway operations

lchat tunnel serve --relay-domain <domain> [--claims /data/tunnel-claims.db] [--max-relays 200] [--claim-idle-days 45]
  • Use a dedicated domain, not the trial/instance domain β€” relayed content shares its reputation. It needs a wildcard A record and a wildcard cert (same DNS-01 setup 11ch.at uses).
  • Claims persist in the gateway's own sqlite (relay_claims: host, pubkey, timestamps). Routes are the ordinary registry service rows; on gateway restart stale r-% rows are swept and reappear as clients reconnect (within ~32s).
  • Grace window: 15 minutes by default. A sleeping relay answers 503 with an honest "this space's machine is offline" message.
  • lchat tunnel kill r-….<domain> withdraws the route; the claim stays, so the same keypair gets the same hostname back on reconnect. Add --forget to also delete the claim β€” the hostname returns to the pool and the keypair starts fresh. That's the kick for a test or abusive relay.
  • Abandoned claims free themselves: an hourly janitor deletes claims whose owner hasn't connected for --claim-idle-days (default 45). Currently-connected relays are never swept, however old their claim.

Honest limits (put these on any page that sells it)

  • Your space's uptime is your machine's uptime. Lid closes, space naps.
  • Throughput is your home uplink, relayed twice through the gateway box.
  • TLS terminates at the gateway (hosted-grade transport trust; content is E2EE regardless). Phase 2 β€” SNI passthrough, where your machine holds its own certificate and the relay sees only opaque bytes β€” is designed in #738 and is the reason relay routes stay a distinct concept.

Not in Phase 1 (see #738)

Memorable/chosen slugs, bring-your-own-domain (CNAME), SNI passthrough, relay plans/billing, and gateway sharding.