Skip to content

Installation

LyEve runs from two container images, the engine and the admin console, against a database you provide. These images are the supported install. See Source code for what is published.

This page covers the choices: which database, how to run the admin console beside the engine, what production refuses, and how to start before you have every setting. To try LyEve on your laptop first, the Quickstart starts a database and the engine for you.

The engine stores everything in one database:

DatabaseDATABASE_URL starts with
PostgreSQLpostgres://
MySQL 8 or latermysql://
SQL Server and Azure SQLsqlserver://

The engine picks the database from that scheme and creates its tables on first start. If you need a managed database, Deployment covers Supabase and Neon.

Use a dedicated database user. A production engine refuses to start as the database's default superuser (postgres on PostgreSQL, root on MySQL, sa on SQL Server). On PostgreSQL, use sslmode=require unless the database is on a private network. A production engine logs a warning on every start when the connection can run without TLS.

On SQL Server, turn on read committed snapshot isolation before you take traffic:

ALTER DATABASE [your_db] SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [model] SET READ_COMMITTED_SNAPSHOT ON;

Without it, a read can lose a deadlock against a concurrent write, and the request fails. The engine checks the setting at start and logs these exact statements when it is off. It does not run them, because the first one disconnects every other session on the database, so pick a maintenance window. Setting it on model means a database created later already has it.

Terminal window
docker run -d --name lyeve-engine \
-e APP_ENV=development \
-e DATABASE_URL="postgres://lyeve:secret@db.example.com:5432/lyeve?sslmode=require" \
-e JWT_SECRET="$(openssl rand -hex 32)" \
-e ENCRYPTION_KEY="$(openssl rand -hex 32)" \
-p 3001:3001 \
-p 3002:3002 \
ghcr.io/lyeve-labs/lyeve-core:latest

Port 3001 serves the Admin API and port 3002 the Content API. The engine refuses to start without DATABASE_URL, JWT_SECRET and ENCRYPTION_KEY, in every environment. APP_ENV defaults to production, which refuses a weak configuration, so the command above sets development for a first run.

VariableDefaultPurpose
DATABASE_URLrequiredConnection string for PostgreSQL, MySQL or SQL Server
JWT_SECRETrequiredFallback signing secret, at least 16 characters. Sessions are signed with an Ed25519 key the engine creates on first start and keeps at JWT_KEY_PATH. Outside production, an engine that cannot write that key signs with this secret instead
ENCRYPTION_KEYrequiredKey for encrypting stored secrets. At least 32 characters and different from JWT_SECRET
APP_ENVproductiondevelopment or production
ADMIN_LISTEN_ADDR0.0.0.0:3001Address of the Admin API
API_LISTEN_ADDR0.0.0.0:3002Address of the Content API
LYEVE_LICENSE_KEYemptyYour license token or key. Empty runs the free tier. See Licensing and tiers
LYEVE_PLUGINSemptyComma-separated list of features to start. Empty starts every feature your license covers
LYEVE_SETUP_TOKENemptyA setup token you choose, 16 characters or more. Set it when more than one replica runs. The Quickstart explains why

Configuration lists every variable.

With APP_ENV unset or production, the engine also requires:

VariableRequirement
SECURE_COOKIEtrue, so session cookies are only sent over HTTPS
RATE_LIMIT_RPSA per-client request ceiling above zero. Unset turns the limiter off, which production refuses
LYEVE_AUDIT_HMAC_KEYExactly 64 hex characters. Generate one with openssl rand -hex 32
JWT_EXPIRY_SECS3600 or less
LYEVE_CONSOLE_URLAn https address when set

A refused start prints every problem at once. The Production checklist covers the rest of a production setup.

Terminal window
docker run -d --name lyeve-admin \
-e CORE_INTERNAL_URL=http://<engine-host>:3001 \
-e CORE_API_INTERNAL_URL=http://<engine-host>:3002 \
-e ORIGIN=http://localhost:3000 \
-e PORT=3000 \
-p 3000:3000 \
ghcr.io/lyeve-labs/lyeve-admin:latest
VariablePurpose
CORE_INTERNAL_URLWhere the admin console reaches the engine. It sends both /api/admin and /api/v1 calls to this one address, so put a proxy in front of the two engine ports
CORE_API_INTERNAL_URLWhere the console sends the /api/v1 calls it makes itself, such as the ones the API reference page runs: the engine's port 3002 or the proxy in front of it. The console refuses to start without it, because its fallback is the console's own port
ORIGINThe URL you open in the browser. It has to match exactly, or sign-in fails its CSRF check
PORTThe port the console listens on. The default is 3002, which collides with the Content API on a shared host
ADMIN_CONSOLE_KEYOptional. The same value, at least 32 characters, on the engine and the console. The console then signs each call with the browser's address, so sign-in limits count each person rather than the console

Docker Compose runs both images with the proxy already configured, and is the shortest path to a working console.

Open http://localhost:3000. A new install redirects to /setup, which asks for the setup token, then an email address and a password for the first administrator. Step 2 of the Quickstart says where the token is.

You can start the engine before you have decided on its database and secrets. With LYEVE_SETUP_MODE=true, a missing DATABASE_URL, JWT_SECRET or ENCRYPTION_KEY no longer stops the start:

Terminal window
docker run -d --name lyeve-engine \
-e LYEVE_SETUP_MODE=true \
-p 3001:3001 -p 3002:3002 \
ghcr.io/lyeve-labs/lyeve-core:latest

In setup mode the engine connects to no database and serves only setup:

RequestAnswer
GET /healthz, GET /startup200, so an orchestrator keeps the container running
GET /readyz503 with "mode":"setup", so a load balancer sends it no traffic
GET /api/admin/setup200 with "setup_required":true and "mode":"setup"
GET /api/admin/setup/statusWhat is missing, with the X-Setup-Token header
Anything else503 with the code SETUP_REQUIRED

Open the admin console. It asks for the setup token from the engine's log, then lists what is missing, with the environment lines and a lyeve.yaml snippet to paste. A missing secret comes with a value the engine generated for this start, shown once. Set the values where your deployment keeps them, restart the engine, and the console moves on to creating the first administrator. The same report is available without the console:

Terminal window
curl -H "X-Setup-Token: <token>" http://localhost:3001/api/admin/setup/status

Setup mode covers those three settings only. A production engine still refuses to start on the other checks above, and the error names them. The engine never writes the values anywhere and cannot restart its own container.

Your engine is running. Continue with step 1 of the Quickstart to create the first administrator, get a token and write your first entry.