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.
| Changeable | Notes |
|---|---|
| Log format and level | LOG_FORMAT=json if you have a pipeline. Note CORECRUX_LOG_FORMAT is a no-op that every shipped manifest sets |
| Redaction posture | CORECRUXD_REDACT=on removes; the default counts without removing |
| Route-auth enforcement | Defaults to shadow mode: it logs a violation and lets the request through. Flip to enforce after a soak |
| The optional feature flags | Coordination, orchestrators, punchcards, activity log, cost lens, identity links, consolidation scheduler, all listed in §1.6 |
| Retention windows | Observation retention, ephemeral GC, receipt days |
| Which console surfaces appear | Several 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.
GET /redirects to/console(console.rs:300).GET /consoleserves the single-page shell (console.rs:301).GET /console-v2/{name}serves the four JavaScript modules and the PWA assets (console.rs:303).
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.73andhttp://crux(console.rs:60). Override withCORECRUXD_CONSOLE_ALLOWED_ORIGINS, comma-separated. Entries that are not a realhttp(s)://host, including a literal*and the stringnull, 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.1or[::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.
| Surface | Flag or config | Default | What it lights up | ||
|---|---|---|---|---|---|
| Coordination / Live board | CORECRUXD_COORD | on (config.rs:1336) | Rings › Live board; the Fleet panel's coord lane | ||
| Orchestrators | CORECRUXD_ORCHESTRATORS | off (agentgraph_kinds.rs:145) | Rings › Orchestrators | ||
| Punchcards | CORECRUXD_PUNCHCARD = off \ | advisory \ | enforce | off (agentgraph_kinds.rs:162) | Rings › Punchcards; lease chips in the Fleet panel |
| Activity log | CORECRUXD_FEATURE_ACTIVITY_LOG | off (activity.rs:58) | Work › Activity, the Activity ticker, the glance sparklines | ||
| Cost lens | CORECRUXD_FEATURE_COST_LENS | off (cost.rs:30) | Both Meters pages | ||
| Identity links | CORECRUXD_IDENTITY_LINKS | off (config.rs:1375) | Trust › Identity | ||
| Passport mint requests | CORECRUXD_FEATURE_PASSPORT_MINT_REQUESTS | off (config.rs:961) | Trust › Pending mints | ||
| Consolidation scheduler | CORECRUXD_CONSOLIDATION_SCHEDULER | off (config.rs:1328) | Memory › Review's surfaced-run queue | ||
| ExecPlan work board | CRUX_EXECPLANS_ROOT | unset (work_execplans.rs:58) | ExecPlan items on the work board and the Rings ring | ||
| Engine mediation | CORECRUXD_ENGINE_BASE_URL | unset (engine_console.rs:80) | Trust › Mediation; the Engine tile; Explorer's WikiCrux backend | ||
| Link graph | CORECRUXD_CORECRUX_GRAPH_BASE_URL | unset (console.rs:761) | The Link graph destination (hidden from the rail entirely when unset) | ||
| Observe / audit trail | CORECRUXD_OBSERVE | off (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.
| # | Check | Why |
|---|---|---|
| 1 | CORECRUXD_AUTH_MODE is a JWT mode | The dev modes have no tenant isolation |
| 2 | CORECRUXD_DATA_DIR is absolute | The default is relative to the working directory |
| 3 | A TLS-terminating proxy is in front | The daemon has no TLS on any plane |
| 4 | /metrics is restricted at the network layer | Unauthenticated, and it leaks topology |
| 5 | CORECRUXD_REDACT=on if logs leave the host | The default counts without removing |
| 6 | LOG_FORMAT=json if you parse logs | CORECRUX_LOG_FORMAT is a no-op |
| 7 | CORECRUXD_ROUTE_AUTH=enforce after a shadow soak | The default logs violations and allows them |
| 8 | CORECRUXD_PASSPORT_CLAIM_ON_STARTUP=0 if air-gapped | It is on by default and reaches the internet once |
| 9 | CORECRUXD_CONSOLE_ALLOWED_ORIGINS set to your real origin | Otherwise three unrelated defaults apply |
| 10 | A backup of passport.key exists before anything writes | Lose 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
- crates/corecruxd/src/config.rs:830,
console_enableddefaults true - crates/corecruxd/src/console.rs:294, the console router
- crates/corecruxd/src/console.rs:248,
resolve_allowed_origins - crates/corecruxd/src/http/health.rs:276, the first readiness gate
- crates/corecruxd/src/config.rs:1336,
coord_enableddefaults true - crates/corecruxd/src/agentgraph_kinds.rs:162,
punchcard_modedefaults off - crates/corecruxd/console/v2/shell.html:5695, the secure-context guard on the service worker

