Operations · 1. First run

Four decisions are effectively permanent, everything else you can change later, and the daemon refuses to start until you have made the first one. This chapter is a how-to: make the four decisions, start the process, confirm it is healthy, open the console.

Configuration values in full are in chapter 5 of the internals set. The 25 conditions that make the daemon exit before serving are in chapter 4 §4.3. This chapter is the shortest path through both.

1.1 The four decisions

Think of these the way you would think of choosing a database's data directory and its authentication scheme. They are cheap now and expensive in six months.

1. Which auth mode. There is no default. corecruxd exits with CORECRUXD_AUTH_MODE must be set explicitly if you do not set one. Four values exist: off, dev_scopes, jwt_hs256, jwt_jwks. The two dev modes are unauthenticated self-assertion with no tenant isolation, and the daemon will refuse to bind them to anything but loopback without an explicit override. For anything another machine can reach, this is a JWT mode.

2. Where the data directory lives, as an absolute path. The default is the relative ../CoreCruxData/v1, resolved against the working directory. Start the daemon from two different directories and you get two silently divergent stores, each with its own lock, neither aware of the other. Set CORECRUXD_DATA_DIR to an absolute path, always.

3. What is reachable, and through what. The daemon terminates no TLS on any plane. Either keep it on loopback and publish through a reverse proxy, or put a TLS-terminating proxy directly in front of it. /metrics is unauthenticated and leaks shard ids, node topology and hashed tenant ids, so restrict it at the network layer regardless.

4. Whether the passport claim goes out. On a default configuration the daemon makes exactly one outbound call at start-up, to claim its passport. Set CORECRUXD_PASSPORT_CLAIM_ON_STARTUP=0 for air-gapped or privacy-sensitive deployments. This is the only decision of the four that is genuinely reversible with no consequence.

1.2 What you can change any time

Do not agonise over these on day one. Every one of them is a restart away from a different value.

ChangeableNotes
Log format and levelLOG_FORMAT=json if you have a pipeline. Note CORECRUX_LOG_FORMAT is a no-op that every shipped manifest sets
Redaction postureCORECRUXD_REDACT=on removes; the default counts without removing
Route-auth enforcementDefaults to shadow mode: it logs a violation and lets the request through. Flip to enforce after a soak
The optional feature flagsCoordination, orchestrators, punchcards, activity log, cost lens, identity links, consolidation scheduler, all listed in §1.6
Retention windowsObservation retention, ephemeral GC, receipt days
Which console surfaces appearSeveral console panes are gated on a flag or on a configured upstream, and each says so on its own face

1.3 A minimum working environment

For a networked deployment behind a TLS-terminating proxy:

CORECRUXD_AUTH_MODE=jwt_hs256
CORECRUXD_JWT_HS256_SECRET=<at least 32 bytes>
CORECRUXD_DATA_DIR=/data
CORECRUXD_HTTP_HOST=0.0.0.0
LOG_FORMAT=json
CORECRUXD_REDACT=on
CORECRUXD_PASSPORT_CLAIM_ON_STARTUP=0

For a local, single-operator daemon on your own machine, where you accept that anyone who can reach loopback has full power:

CORECRUXD_AUTH_MODE=dev_scopes
CORECRUXD_DATA_DIR=/home/you/.local/share/corecrux

Use =1 and =0 for every boolean. The daemon has nine different boolean parsing rules across its flags and six of them do not trim whitespace, so a trailing newline from a systemd EnvironmentFile= or a Kubernetes configMapKeyRef silently reads as off. 1 and 0 work under every rule.

1.4 Starting it, and what healthy looks like

Start the process. On a first boot against an empty data directory you should see the daemon create the directory, take the LOCK, replay nothing, and bind three listeners.

Then run the three checks, in this order.

Check one: is it alive at all.

curl -s http://127.0.0.1:14800/healthz

/healthz always returns 200 with ok: true. Nothing in the handler can make it fail. It tells you the process is answering and nothing more, treat it as a liveness probe only.

Check two: is it ready to serve.

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:14800/readyz

200 means all nine readiness gates pass. 503 means at least one failed, and the body names which. The nine gates are data_dir_lock_held, routing_loaded, replicated_commit_dataplane, replicated_commit_topology, read_retry_failed_threshold, projection_snapshots_valid, corruption_state_clear, control_evidence_ok and data_dir_capacity (health.rs:276-332).

On a fresh, healthy daemon that is not configured for replication, all nine pass. If replicated_commit_dataplane is failing, you have selected ReplicatedCommit on a build with no dataplane; that gate cannot pass in this edition and the fix is to not select that mode.

Check three: does it know who it is.

curl -s http://127.0.0.1:14800/v1/version

This returns the build version and the runtime capability plan. The console reads the same document to decide which capability-gated panes to show, so if a pane is missing later, this is where the answer is.

1.5 Opening the console

The console is served by the daemon itself, from assets embedded in the binary. There is nothing to deploy and nothing on disk to serve.

The console is on by default. CORECRUXD_CONSOLE_ENABLED=0 removes every one of those routes (config.rs:830, console.rs:294).

Two things about the console's own network posture, both of which bite on first run:

  • Cross-origin requests to the console asset routes are allowlisted, not wildcarded. The default allowlist is three origins: https://crux.cuecrux.com, http://100.70.12.73 and http://crux (console.rs:60). Override with CORECRUXD_CONSOLE_ALLOWED_ORIGINS, comma-separated. Entries that are not a real http(s)://host, including a literal * and the string null, are dropped, and if nothing usable survives the defaults apply (console.rs:248).
  • The service worker is registered only in a secure context. HTTPS, localhost, 127.0.0.1 or [::1] (shell.html:5695). Over plain HTTP to a LAN address the console still works; it just is not installable and does not cache its shell.

1.6 The optional surfaces, and their defaults

Several console panes exist but stay dark until a flag is set or an upstream is configured. Turning them on is a first-run decision only in the sense that it is easier to do now than to explain their absence later.

SurfaceFlag or configDefaultWhat it lights up
Coordination / Live boardCORECRUXD_COORDon (config.rs:1336)Rings › Live board; the Fleet panel's coord lane
OrchestratorsCORECRUXD_ORCHESTRATORSoff (agentgraph_kinds.rs:145)Rings › Orchestrators
PunchcardsCORECRUXD_PUNCHCARD = off \advisory \enforceoff (agentgraph_kinds.rs:162)Rings › Punchcards; lease chips in the Fleet panel
Activity logCORECRUXD_FEATURE_ACTIVITY_LOGoff (activity.rs:58)Work › Activity, the Activity ticker, the glance sparklines
Cost lensCORECRUXD_FEATURE_COST_LENSoff (cost.rs:30)Both Meters pages
Identity linksCORECRUXD_IDENTITY_LINKSoff (config.rs:1375)Trust › Identity
Passport mint requestsCORECRUXD_FEATURE_PASSPORT_MINT_REQUESTSoff (config.rs:961)Trust › Pending mints
Consolidation schedulerCORECRUXD_CONSOLIDATION_SCHEDULERoff (config.rs:1328)Memory › Review's surfaced-run queue
ExecPlan work boardCRUX_EXECPLANS_ROOTunset (work_execplans.rs:58)ExecPlan items on the work board and the Rings ring
Engine mediationCORECRUXD_ENGINE_BASE_URLunset (engine_console.rs:80)Trust › Mediation; the Engine tile; Explorer's WikiCrux backend
Link graphCORECRUXD_CORECRUX_GRAPH_BASE_URLunset (console.rs:761)The Link graph destination (hidden from the rail entirely when unset)
Observe / audit trailCORECRUXD_OBSERVEoff (agentgraph_kinds.rs:140)Session audit export

None of these fabricates data when off. Each pane renders an honest empty state that names the flag. That is the design, and it is why "the page is blank" is a diagnosis, not a symptom, see chapter 8.

1.7 The first-run checklist

Ten items. Every one corresponds to a default that a production operator would not choose.

#CheckWhy
1CORECRUXD_AUTH_MODE is a JWT modeThe dev modes have no tenant isolation
2CORECRUXD_DATA_DIR is absoluteThe default is relative to the working directory
3A TLS-terminating proxy is in frontThe daemon has no TLS on any plane
4/metrics is restricted at the network layerUnauthenticated, and it leaks topology
5CORECRUXD_REDACT=on if logs leave the hostThe default counts without removing
6LOG_FORMAT=json if you parse logsCORECRUX_LOG_FORMAT is a no-op
7CORECRUXD_ROUTE_AUTH=enforce after a shadow soakThe default logs violations and allows them
8CORECRUXD_PASSPORT_CLAIM_ON_STARTUP=0 if air-gappedIt is on by default and reaches the internet once
9CORECRUXD_CONSOLE_ALLOWED_ORIGINS set to your real originOtherwise three unrelated defaults apply
10A backup of passport.key exists before anything writesLose it and receipts stop verifying, permanently

Item 10 is the one people skip. passport.key is not recoverable and it also encrypts stored integration credentials through a derived subkey. Chapter 9 is the full procedure.

Sources