clone

a self-hosted sync node for lofi apps: jazz sync over iroh, ticket-gated, with no static ip or cloud needed

docs/convergence-validated
lofi-node / README.md
README.md 3.9K rendered
1![lofi-node — self-host the sync backend for lofi apps](docs/assets/brand/lofi-node-github-banner.png)23# @nzip/lofi-node45**Self-host the sync backend for [lofi](https://github.com/FelineStateMachine/lofi) apps: one daemon6embedding a Jazz sync server, iroh peer-to-peer transport, and ticket-gated access.**78Issue a ticket carrying location + secret; the app stores it passkey-encrypted and syncs against9your node. Pair homes by ticket — no static IPs, no cloud — and choose where your data lives.1011[Documentation](https://lofi.host/node) · [API reference](https://lofi.host/node/api) ·12[JSR package](https://jsr.io/@nzip/lofi-node) · [MIT License](LICENSE)1314Building with an AI agent? Feed it [llms.txt](https://lofi.host/node/llms.txt) for an index of the15node documentation, or [llms-full.txt](https://lofi.host/node/llms-full.txt) for the complete docs16and API reference in one file.1718## Quick start1920Run straight from JSR with `dx` (Deno's npx — `deno x`):2122```sh23dx -A jsr:@nzip/lofi-node/cli init --port 4802 # ticket-gated by default24dx -A jsr:@nzip/lofi-node/cli start # gate URL + node-pairing ticket25dx -A jsr:@nzip/lofi-node/cli ticket issue --label phone # app-connect ticket (shown once)26```2728Equivalent forms:2930```sh31deno run -A jsr:@nzip/lofi-node/cli start # plain deno32deno install -g -A -n lofi-node jsr:@nzip/lofi-node/cli # persistent `lofi-node` command33```3435> Freshly published versions sit behind Deno's 24-hour36> [minimum-dependency-age](https://docs.deno.com/go/minimum-dependency-age) supply-chain gate.37> Within that window use `deno run --minimum-dependency-age=0 -A jsr:@nzip/lofi-node/cli …`38> (`deno x` does not yet accept the override).3940On first start the native iroh layer is downloaded from this repo's GitHub release for the matching41version and sha256-verified against digests pinned inside the package. No Deno at all? Grab a42compiled binary from the [releases](https://github.com/FelineStateMachine/lofi-node/releases) (macOS43arm64 and Linux x86_64; the macOS binary is unsigned — clear quarantine with44`xattr -d com.apple.quarantine lofi-node-*`). Linux aarch64 is pending an upstream jazz-napi45`linux-arm64-gnu` build.4647Or run the container image:4849```sh50docker run --rm -v lofi-node-data:/data ghcr.io/felinestatemachine/lofi-node \51 init --dir /data --port 480252docker run -d --name lofi-node --network host -v lofi-node-data:/data \53 ghcr.io/felinestatemachine/lofi-node54```5556The image is linux/amd64 (arm64 hosts run it under emulation, per the jazz-napi gap above);57[compose.yaml](compose.yaml) is the reference deployment, and58[the deployment guide](https://lofi.host/node/docs/beyond-the-lan) covers networking and persistence59choices.6061As a library:6263```sh64deno add jsr:@nzip/lofi-node65```6667```ts68import { createSyncNode } from "@nzip/lofi-node";6970const node = await createSyncNode({ appId, backendSecret, adminSecret, dataDir: "./data" });71node.url; // -> JAZZ_SERVER_URL for the lofi app72```7374Tutorials (self-hosting, pairing, store provisioning), guides, and reference live at75[lofi.host/node](https://lofi.host/node). The normative contracts stay in this repo:76[docs/app-ticket.md](docs/app-ticket.md) (ticket format, scopes, store-status — with77[conformance fixtures](docs/fixtures/app-ticket-fixtures.json)) and78[docs/hosting-lofi-apps.md](docs/hosting-lofi-apps.md) (validated hosting walkthrough).7980## Developing lofi-node8182```sh83deno task native # build the native addon (Rust; once, or per vendored change)84deno task check # fmt --check + lint + typecheck — the PR gate85deno task test # full suite; iroh/jazz integration auto-skips without the addon86```8788The native layer is a provenance-tracked vendor of upstream89[n0-computer/iroh-ffi](https://github.com/n0-computer/iroh-ffi)'s `iroh-js` crate — see90[native/iroh-js/UPSTREAM.md](native/iroh-js/UPSTREAM.md) for the vendoring contract and91[CONTRIBUTING.md](CONTRIBUTING.md) for boundaries and the release procedure.