Skip to main content
Version: v5.7.0

opschain server start

Included from Basic tier

Start the OpsChain server in the foreground: HTTP(S) API, data store, scheduler, runner protocol and log streaming, as one process. The command prints the listen URL once the socket is open —

opschain server start
opschain server listening on http://127.0.0.1:8443

— then serves until SIGTERM or SIGINT. The first signal begins a graceful shutdown (drain runners and parked polls, stop the scheduler, close the store) with a 30-second grace period; a second signal abandons the grace period and stops hard.

Configuration layering​

Configuration resolves lowest-to-highest:

  1. $OPSCHAIN_HOME/server/config.yaml and server/keys.env — written by opschain server configure. Print the annotated key catalog with opschain server configure and its template flag (see opschain docs cli/server-configure) rather than guessing key names; the running server also serves the same catalog at GET /api/admin/config.
  2. Environment variables — the keys.env names (OPSCHAIN_TOKEN_SECRET_KEY, OPSCHAIN_PRIMARY_KEY, OPSCHAIN_KEY_DERIVATION_SALT), OPSCHAIN_LDAP_PASSWORD, OPSCHAIN_SERVER_ADMIN_TOKEN, OPSCHAIN_ENABLE_BASIC_AUTH, OPSCHAIN_CLUSTER_NAME, the OPSCHAIN_LDAP_* overlay and any OPSCHAIN_VAULT_* values.
  3. Flags — a flag explicitly passed on this invocation wins over the file value even when the flag's value equals its default.

On PostgreSQL the token secret is a start requirement: when neither OPSCHAIN_TOKEN_SECRET_KEY (environment or keys.env) nor the stored token.secret_key supplies one, server start refuses by name — token secret: a PostgreSQL server needs one — set OPSCHAIN_TOKEN_SECRET_KEY … or store token.secret_key — rather than serve every caller as the superuser. opschain server configure writes the key, so a configured home never hits this; a settings read that fails at boot refuses the same way instead of opening. Only a test lane declares the open posture, with server.unauthenticated_postgres: true in config.yaml, and the hardened posture refuses that declaration. The SQLite store is unchanged: it has no auth stack either way.

Flags​

FlagMeaning
--listen <host:port>Listen (bind) address; port 0 picks a free one. Default 127.0.0.1:8443 — loopback — on every store (the config file's listen when set). On the embedded SQLite store a non-loopback address is honoured and called out in the startup notice, because that server has no sign-in.
--store <path or DSN>The data store: a SQLite database path, or a postgres:// DSN. Parameters left out of the DSN fall back to the standard PG* environment variables. Default: <opschain home>/opschain.db — the development harness below; the full server needs postgres://.
--tls-cert <file>TLS certificate file. Set both TLS flags to serve HTTPS; without them the server speaks plain HTTP (loopback/dev).
--tls-key <file>TLS private key file.
--admin-token <token>Static admin bearer token admitted to the admin service on a store WITHOUT the auth stack, where it is the sole guard (default off). On PostgreSQL with a resolvable token secret the lane is retired: the token is refused with the typed ERROR_REASON_ADMIN_TOKEN_RETIRED answer, a boot notice says so, and admin surfaces authenticate user sessions and API keys through the /admin RBAC gate. Falls back to OPSCHAIN_SERVER_ADMIN_TOKEN when the flag is empty.
--confirm-eulaAccept the LimePoint EULA on a fresh installation's first start (read it with opschain eula). Recorded once, then inert.
--dev-run-seamMount the admin-gated run-creation seam under /admin/e2e/runs (interim, superseded by the v1 API).
--lease-ttl <d>Job lease TTL before a silent runner's step fails as runner_lost (default 3m).
--poll-window <d>Long-poll park window for runner job acquisition (default 50s).
--replica-retention <d>How long a dead scheduler replica's membership row stays visible before the leader reaps it (default 24h).

Global flags that matter here: --home picks the server home the configuration is read from; --log-file <path> writes JSON log lines to a rotated file instead of stderr. When the config file's logging: block names a file, file logging engages without the flag; the flag overrides the path while the rotation settings (size, age, backup count) always come from the logging: block.

The embedded SQLite store: a development harness​

Started with no store configured, the server runs on the embedded SQLite file and is a development harness — the run engine behind the run/step/log API, the runner and agent fleet, licensing and the local secret store — for tests, runner-fleet play and GUI development against its API. It has no sign-in, so the binary labels it: it binds to loopback unless --listen says otherwise, it does not serve the GUI (the root URL answers a plain page saying the GUI needs a server on PostgreSQL), and once the socket is open it prints this notice on the notice stream (stderr, or the log file):

opschain server: development harness on the embedded SQLite store (no `store` configured)
opschain server: serves: the run engine behind the run/step/log API, the runner and agent fleet, licensing, the local secret store
opschain server: does not serve: users and sign-in, the estate, templates, the workflow catalog, notifications, governance, providers, the web GUI (the root URL answers a page saying so)
opschain server: bound to http://127.0.0.1:8443 (loopback — the default on this store; pass --listen host:port or set listen: in config.yaml to bind elsewhere)
opschain server: to evaluate the full server — PostgreSQL, the server and the web GUI in one command — run the go-opschain Docker Compose (`./configure`, then `docker compose up`); `opschain docs storage` has the route and the DSN it exposes

With an explicit non-loopback --listen the fourth line reads bound to http://0.0.0.0:8443 — NOT loopback: this harness has no sign-in, so anything that can reach the address can use it. The notice never carries a secret. A server on PostgreSQL prints no such notice and binds exactly as configured. opschain docs storage ("The SQLite server is a labelled development harness" and "Evaluating the full server") has the whole contract.

The EULA gate​

A fresh installation refuses to start until the LimePoint EULA is accepted: interactively (on a terminal the agreement is printed and the word accept is required), with --confirm-eula, or with the config file's eula: accepted: true. Acceptance is recorded once per installation and a later EULA revision never re-gates.

Exit codes​

CodeMeaning
0Clean shutdown after a signal.
1The server failed to configure, listen or serve (the error is printed).
2Usage error — unknown flag or stray argument.

See also​

  • opschain docs cli/server-configure — write the configuration this command reads.
  • opschain docs cli/server-backup and opschain docs cli/server-restore — embedded-deployment backups.
  • opschain docs cli/eula — read the agreement the first start requires.
  • opschain docs storage — the stores, the harness contract and the one-command evaluation route.
  • opschain learn 0.1 — install and first contact.