trusty-console
Web dashboard that detects the trusty services running on your machine and shows a home page with a card per service.
Phase 0 (P0) scope
- Service detection:
trusty-search,trusty-memory,trusty-analyze - Three status levels: Running (daemon up + health-checked), Available (binary on PATH, no daemon), Absent (binary not installed)
- Embedded Svelte SPA served from the binary
GET /api/console/servicesJSON API
Usage
# Start the console (default: 127.0.0.1:7788 — localhost only)
# Custom port + open browser
# Expose on both localhost AND the machine's Tailscale IPv4 (tailnet + loopback)
Do not bind 0.0.0.0 (ADR-0018). A wildcard listener has no tailnet address
of its own, so the peer gate (below) refuses every request on it, local ones
included. Use --tailscale for tailnet access.
Tailscale / tailnet exposure
--tailscale is the recommended way to make the console durable across tailnet
sessions without exposing it on the public LAN.
How it works
When --tailscale is passed (or TRUSTY_CONSOLE_BIND=tailscale is set), the
console:
- Runs
tailscale ip -4to detect the machine's Tailscale IPv4 (e.g.100.x.y.z). - Binds two TCP listeners on the configured port:
127.0.0.1:<port>— loopback, for local tooling.<ts-ip>:<port>— Tailscale IP, behind the tailnet peer gate.
- Serves the same router on both listeners.
Access model
Loopback listeners are served ungated. Every other listener — the
--tailscale address, or any non-loopback --http / TRUSTY_CONSOLE_BIND
address — goes through the tailnet peer gate, on every route. The gate serves
a request only when the peer node belongs to this machine's own Tailscale login
and is untagged, the Host header names that listener exactly, and any
Origin is that same address. Anything else, including a peer whose identity
tailscale whois cannot determine, gets 403.
Only the primary (loopback) address is written to the discovery file.
If tailscale ip -4 fails (Tailscale not installed / not running), a warning
is logged and the server falls back to localhost-only — it does not crash.
Tailnet URL
http://100.x.y.z:7788
Replace 100.x.y.z with the machine's Tailscale IP (shown in tailscale status
or tailscale ip -4).
Bind precedence (highest to lowest)
| Priority | Mechanism | Example |
|---|---|---|
| 1 | --http <addr> (non-default value) |
--http 127.0.0.1:9000 |
| 2 | TRUSTY_CONSOLE_BIND env var |
TRUSTY_CONSOLE_BIND=tailscale |
| 3 | --tailscale flag |
trusty-console serve --tailscale |
| 4 | Default | 127.0.0.1:7788 (local only) |
TRUSTY_CONSOLE_BIND accepts:
tailscale— dual-listener mode (loopback + Tailscale IP).- Any
<host>:<port>string — explicit bind (same as--http); a non-loopback address is served behind the peer gate. - Empty / unset — no effect; falls through to next priority level.
Durable tailnet exposure via launchd (macOS)
Add TRUSTY_CONSOLE_BIND=tailscale to the launchd plist so the env var is
present on every restart:
EnvironmentVariables
TRUSTY_CONSOLE_BIND
tailscale
Or pass the flag directly in ProgramArguments:
ProgramArguments
/Users/you/.cargo/bin/trusty-console
serve
--tailscale
Either approach survives reboots without manual intervention.
CORS
The server sets CorsLayer::permissive() (wildcard * on all origins). This
is intentional for a local developer dashboard and does not change with
--tailscale.
Building the UI
The Svelte SPA is built automatically by build.rs when pnpm is on PATH.
To skip the UI build (CI, no Node):
SKIP_UI_BUILD=1
A vanilla-JS placeholder (ui/dist/index.html) is committed to the repo so the
binary always embeds a working UI even without a Node build step.