Hosting
A hosted Lix lives on a server. The server owns its storage and authentication. Clients can execute directly on the server or keep a synchronized local replica.
| Client mode | Use for |
|---|---|
remote | The simplest setup. Every operation executes on the server. |
sync | Responsive and offline apps. Operations execute on a local replica. |
Both modes use the same Lix URL and server protocol. See Collaboration and Sync to choose a mode.
The simplest client uses remote mode:
import { openLix } from "@lix-js/sdk";
const lix = await openLix({
server: {
mode: "remote",
url: "https://lixray.com/lix/01936f4e-7b6c-7c3d-8f9a-123456789abc",
},
});
There are two ways to get a server:
| Option | Who runs it | Use for |
|---|---|---|
| lixray.com | The Lix team | Getting started, and teams without a host |
| Your own host | You | Your infrastructure, your auth, your data |
Both speak the same protocol. Only the URL changes in client code.
Official host: lixray.com
LixRay is the official Lix host. Copy the immutable Lix
connection URL and pass it to openLix():
import { openLix } from "@lix-js/sdk";
const lix = await openLix({
server: {
mode: "remote",
url: "https://lixray.com/lix/01936f4e-7b6c-7c3d-8f9a-123456789abc",
headers: async () => ({
Authorization: `Bearer ${await getAccessToken()}`,
}),
},
});
The connection URL is an absolute HTTPS URL whose path is exactly
/lix/{uuid}. HTTP is accepted only for loopback development. It carries no
query, fragment, credentials, or deployment-path prefix. Human-readable
namespace and project URLs are separate web-page addresses, not Lix connection
URLs.
Files, SQL, branches, history, and observe() work the same way they do
locally. See Collaboration and Sync.
Host it yourself
Companies that must keep repositories on their own infrastructure can run their own host. There are three interoperable approaches:
- Deploy the ready-made Lix reference server behind your authentication gateway.
- Embed the
lixcrate's protocol handler in a custom Rust host. - Implement the documented Lix Server Protocol independently in another language or architecture.
The reference server is a supported example, not the protocol authority. Every compatible implementation exposes the same wire contract to clients.
Deploy the reference server
The reference server uses SlateDB and S3-compatible object storage and is
published as ghcr.io/opral/lix-server. It provides runtime pooling, caching,
stream leases, timeouts, and graceful recovery. Authentication, authorization,
and resource-existence policy remain the responsibility of a trusted gateway.
See its README for configuration and security
requirements.
Embed the Rust handler
Enable the feature:
[dependencies]
lix = { version = "0.11", features = ["server-protocol"] }
Open a repository and keep one LixServerProtocol for as long as it is hosted:
use lix::server_protocol::{
ServerProtocolContext, ServerProtocolPrincipal,
};
let protocol = lix::open_lix()
.with_storage(storage)
.serve()
.with_lix_id("01936f4e-7b6c-7c3d-8f9a-123456789abc")
.await?;
// Your host authenticates first, then calls the protocol.
let context = ServerProtocolContext {
principal: ServerProtocolPrincipal::Authenticated {
account_id: account_id.to_owned(),
idempotency_scope: "identity-provider:user-123".to_owned(),
},
durable_terminal_storage_notifier: None,
};
let response = protocol.handle(request, context).await;
with_lix_id binds the host's stable resource UUID. It can differ from the
portable identity stored inside a restored snapshot. The protocol validates
that every request targets this bound UUID.
request is a ServerProtocolRequest, which is
http::Request<ServerProtocolBody>. The response is
http::Response<ServerProtocolBody>. Converting your framework's body type into
ServerProtocolBody is the only adapter code you write.
Your host is responsible for three things:
- Authenticate the request and choose a principal. The protocol does not
read tokens, cookies, or certificates. Never derive an
account_idfrom an unverified header. - Resolve the Lix identified by
{lix_id}without creating an unknown target. Pass the complete root/lix/v1/{lix_id}/...request to the protocol; it validates the immutable ID before dispatch. If your product is mounted below a deployment prefix, strip that prefix at the reverse-proxy boundary before dispatch. SDK connection locators themselves never contain a deployment prefix. - Forward the request and the response. Preserve protocol status codes, headers, and body bytes. Keep the Lix runtime alive until every streaming response body closes, including server-sent events (SSE) and snapshot downloads.
Use ServerProtocolPrincipal::Anonymous only where you deliberately allow
anonymous access. Reject bad credentials with 401 before dispatch. Call
LixServerProtocol::close() on shutdown.
Clients connect exactly as they do to lixray.com. Only the URL changes.
The SDK accepts https://host/lix/{lix_id}, derives the versioned API URL,
opens a session, and reconnects observation streams on its own. HTTPS is
required except for HTTP loopback addresses used in local development.
For the wire format, session behavior, and the OpenAPI document, see Lix Server Protocol.
Storage on your own host
The host chooses where bytes live. SlateDB stores a repository on
S3-compatible object storage; RocksDB stores it on a local disk. Clients never
configure this:
JS client ── HTTP ──▶ your Lix server ──▶ SlateDB ──▶ S3