@leumas/imperium-server
Standalone, white-label Imperium production server — the packageable 'run your own Imperium ecosystem' edition. Reuses the @leumas/hosting core (resolve/serve/SEO/mode-endpoints/shield) behind a...
@leumas/imperium-server — host Imperium on your own infra
The standalone, white-label edition of Imperium: point a wildcard domain at it and every subdomain resolves to its own config (mode + data) and renders. It is the same engine the Leumas platform runs — @leumas/hosting — assembled into a small Express app, so a self-hosted instance gets identical resolve, publish gating, SEO, storage endpoints and anti-scrape behaviour.
visitor → wildcard edge (Caddy) → imperium-server worker(s) → @leumas/hosting → your config store
Quick start
node bin/create-imperium.mjs --dir ./my-imperium --domain example.com
cd ./my-imperium
node node_modules/@leumas/imperium-server/src/server.js
The scaffolder creates the runtime layout, generates instance secrets, and seeds the shared __global layer plus one published site so the first boot serves a real page. Re-running it never overwrites existing configs.
What it serves
| Surface | Path |
|---|---|
| Every subdomain's page | GET * — SEO injected into the SPA bundle (or a minimal shell without one) |
| Config resolution | GET /api/hosting/resolve?host=… |
| Custom view types | GET /api/hosting/view-modes (public — anonymous visitors need these to render x-… sites) |
| Storage-backed modes | GET /api/hosting/modes/:siteId/{folder,gallery,exe}/… |
| SEO | /robots.txt, /sitemap.xml (this host), /sitemap-index.xml (all servable sites) |
| Probes | /healthz, /readyz |
Publishing, editing and the member UI live in Leumas Studio — this server is the read/serve plane. Point both at the same store, or run Studio's appliance EXE alongside it.
Configuration
All optional except the base domain.
| Env | Meaning |
|---|---|
PORT | listen port (default 1000) |
IMPERIUM_BASE_DOMAIN | the domain subdomains hang off (example.com) |
IMPERIUM_WEB_DIST | a built leumas-web bundle → full SPA rendering |
LEUMAS_DATA_ROOT | the config store (libSQL) — the connector reads this one |
IMPERIUM_DATA_ROOT | server-local runtime files (license.json) |
IMPERIUM_STORAGE_ROOT | per-site upload roots for folder/gallery/exe modes |
IMPERIUM_PREVIEW_SECRET | must be identical across workers or draft-preview links fail to verify |
IMPERIUM_FOLDER_ROOTS | ;-separated absolute prefixes a folder site may read (self-host only) |
IMPERIUM_RESOLVE_CACHE_MS | resolve read-cache TTL (default 3000, 0 disables) |
IMPERIUM_ALLOW_LEGACY_CONFIGS | serve pre-firstParty configs during a migration |
LEUMAS_LICENSE_SERVER | licensed appliance: entitlement policies come from the signed token |
Entitlements
Two modes, no configuration branching in your code:
- Self-host — the instance's own
entitlement_policiesdocs, layered over the committed
defaults, so hosting works out of the box.
- Licensed appliance (
LEUMAS_LICENSE_SERVER) — the policy ceiling is a Leumas-signed Ed25519
token verified offline; an unreachable platform never bricks the instance before the token's own expiry. Membership assignment stays local to your instance.
Set IMPERIUM_NO_ENTITLEMENTS=1 to serve every published site without the per-owner capability re-check (single-tenant installs).
Scaling
deploy/Caddyfile is a wildcard edge that forwards all of *.example.com to an identical worker pool, preserving the Host header — no per-site routes, ever. Start N copies on 1001…100N, list them in the reverse_proxy block, and Caddy health-checks /healthz.
Each worker is stateless apart from its store; the resolve cache is per-process and TTL-bounded, so workers converge within IMPERIUM_RESOLVE_CACHE_MS of a publish.
Security posture
- Configs serve only when published (hosted) or explicitly flagged
firstParty(operator). - Storage endpoints are traversal-guarded and scoped to
storage/imperium/<siteId>/; raw filesystem
roots are self-host-only and must be allowlisted via IMPERIUM_FOLDER_ROOTS.
- Custom view types render inside a sandboxed iframe with no same-origin access.
- The reverse proxy performs SSRF checks (private/loopback/metadata ranges denied, DNS-rebind pinned).
- The optional per-site shield applies rate limits, user-agent denylists and honeypot paths at the edge.