This guide covers setting up y/hub infrastructure for production.
| Service | Purpose |
|---|---|
| Redis | Real-time message passing |
| PostgreSQL | Document metadata storage |
| S3 | Document blob storage |
Any S3-compatible storage works (AWS S3, Cloudflare R2, MinIO, etc.).
Provision a Redis instance. y/hub uses Redis streams and pub/sub for real-time updates.
Environment variable:
REDIS=redis://localhost:6379
REDIS_PREFIX=yhubCreate a PostgreSQL database and the required tables:
CREATE TABLE IF NOT EXISTS yhub_updates_v1 (
org text,
docid text,
branch text DEFAULT 'main',
gc boolean DEFAULT true,
r SERIAL,
update bytea,
sv bytea,
contentmap bytea,
PRIMARY KEY (org, docid, branch, gc, r)
);
CREATE TABLE IF NOT EXISTS yhub_attributions_v1 (
org text,
docid text,
branch text DEFAULT 'main',
contentmap bytea,
PRIMARY KEY (org, docid, branch)
);Environment variable:
POSTGRES=postgres://user:password@host:5432/databaseCreate an S3 bucket for storing document blobs. The bucket name is configurable.
Environment variables:
S3_ENDPOINT=s3.amazonaws.com # or your S3-compatible endpoint
S3_PORT=443
S3_SSL=true
S3_ACCESS_KEY=your-access-key
S3_SECRET_KEY=your-secret-key
S3_YHUB_BUCKET=yhubYou need to implement an auth server that handles two endpoints. See
bin/auth-server-example.js for a complete working example.
┌────────┐ ┌─────────────┐ ┌────────┐
│ Client │ │ Auth Server │ │ Y/Hub │
└───┬────┘ └──────┬──────┘ └───┬────┘
│ │ │
│ 1. GET /auth/token │ │
│────────────────────▶│ │
│ │ │
│ 2. JWT with yuserid │ │
│◀────────────────────│ │
│ │ │
│ 3. Connect WebSocket with JWT │
│─────────────────────────────────────────▶│
│ │ │
│ │ 4. GET /auth/perm/:room/:userid
│ │◀───────────────────│
│ │ │
│ │ 5. { yaccess: 'rw' }
│ │───────────────────▶│
│ │ │
│ 6. Connection accepted │
│◀─────────────────────────────────────────│
npx 0ecdsa-generate-keypair --name authAdd the generated keys to your environment:
AUTH_PUBLIC_KEY={"kty":"EC","crv":"P-384",...}
AUTH_PRIVATE_KEY={"kty":"EC","crv":"P-384",...,"d":"..."}The client requests a JWT from your auth server. You authenticate the user (via session, OAuth, etc.) and return a signed JWT containing their user ID:
// GET /auth/token
app.get('/auth/token', async (req, res) => {
// Authenticate the user with your existing auth system
const userId = req.session.userId
const token = await jwt.encodeJwt(authPrivateKey, {
iss: 'your-app-name',
exp: time.getUnixTime() + 60 * 60 * 1000, // 1 hour expiry
yuserid: userId // Required: unique user identifier
})
res.send(token)
})When a client connects to y/hub, it calls your permission endpoint to check access. Return the access level for this user and room:
// GET /auth/perm/:room/:userid
app.get('/auth/perm/:room/:userid', async (req, res) => {
const { room, userid } = req.params
// Check your database for user permissions
const access = await checkUserAccess(userid, room)
res.json({
yroom: room,
yaccess: access, // 'rw', 'read-only', or 'no-access'
yuserid: userid
})
})# Redis
REDIS=redis://localhost:6379
REDIS_PREFIX=yhub
# PostgreSQL
POSTGRES=postgres://user:password@host:5432/database
# S3
S3_ENDPOINT=s3.amazonaws.com
S3_PORT=443
S3_SSL=true
S3_ACCESS_KEY=your-access-key
S3_SECRET_KEY=your-secret-key
S3_YHUB_BUCKET=yhub
# Authentication
AUTH_PUBLIC_KEY=...
AUTH_PRIVATE_KEY=...
# Server (optional)
PORT=3002
# Logging (optional)
LOG=*After configuring your environment, run:
npm run initThis creates the PostgreSQL tables and S3 bucket if they don't exist.
The worker handles persistence and cleanup:
npm run start:workerRun at least one worker instance. Multiple workers can run in parallel for higher throughput.
The server handles WebSocket connections:
npm run start:serverMultiple server instances can run behind a load balancer. Ensure the load balancer supports WebSocket upgrades.