A minimal Linked Data Event Stream server: append-only, file-based storage, Ed25519-signed immutable pages, rsync-friendly by design.
Stack: Node.js 24 (native TypeScript, no build step), n3 for RDF parsing,
rdf-validate-shacl for SHACL enforcement, built-in node:crypto for signing,
Caddy for TLS and reverse proxy.
- Accepts N-Quads via
POST /ingest(bearer-token-authenticated) - Validates ingested members against a configurable SHACL shape
- Appends to the currently-open node file (
nodes/NNNNNNNNNN.nq) - When a node crosses a size threshold, closes it durably (fsync + fsync dir),
marks it
0444immutable, writes an Ed25519 signature sidecar (.nq.sig), and rewritesroot.nqatomically to link the new immutable node viatree:relation - Serves everything as N-Quads with correct
Cache-Control: immutablefor frozen pages
Fresh Ubuntu 24.04 or 26.04 as root:
git clone https://github.com/YOUR-USER/ldes-lite.git
cd ldes-lite
sudo bash scripts/setup.sh
Then edit /var/lib/ldes-lite/config.json and /etc/caddy/Caddyfile for your
domain, systemctl start ldes-lite, systemctl reload caddy.
/opt/ldes-lite/ # code (owned root:ldes, read-only for ldes)
/var/lib/ldes-lite/
config.json # server config
shape.ttl # SHACL shape members must conform to
ingest.token # bearer token for POST /ingest
keys/
ed25519.key # Ed25519 private key (400, root)
ed25519.pub # public key, served at /pubkey
data/
root.nq # LDES root Node, rewritten on rotation
nodes/
0000000001.nq # immutable, 0444
0000000001.nq.sig # signature sidecar
...
0000000042.nq # currently open, 0644
GET /— hello world HTML landing page with links to the endpoints belowGET /kitten.jpg— kitten image embedded on the landing pageGET /root— LDES root node withtree:relationlinks to all immutable nodesGET /nodes/NNNNNNNNNN— a specific node (Cache-Control: immutableif frozen)GET /nodes/NNNNNNNNNN.sig— signature sidecarGET /pubkey— public verification key (PEM)GET /health— JSON health probe (no auth):status,openNodeNumber,openNodeSize,nodeCount,uptimeSecondsPOST /ingest— appends members (requiresAuthorization: Bearer <token>)
MIT