2026-07-18 15:23:20 +02:00
|
|
|
# User Workflows
|
|
|
|
|
|
|
|
|
|
This document describes geth from the operator's point of view. Each workflow
|
|
|
|
|
states the intended outcome, the shortest supported command path, the success
|
|
|
|
|
signal, and important trust or durability boundaries.
|
|
|
|
|
|
|
|
|
|
## Choose A Startup Mode
|
|
|
|
|
|
|
|
|
|
### Try geth without keeping state
|
|
|
|
|
|
|
|
|
|
User story: as a curious user or test author, I want an isolated daemon without
|
|
|
|
|
choosing a directory or cleaning it up afterward.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth daemon run --ephemeral
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The command initializes a temporary home, prints its path and a ready-to-copy
|
|
|
|
|
control command, and runs in the foreground. In another terminal:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth --home <printed-path> status
|
|
|
|
|
geth --home <printed-path> node id
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Success means `geth status` reports `geth daemon: running`. Ctrl-C performs a
|
|
|
|
|
graceful shutdown and removes the temporary home. An abrupt process kill may
|
|
|
|
|
leave temporary files for the operating system's normal temp cleanup.
|
|
|
|
|
|
|
|
|
|
### Keep a persistent background node
|
|
|
|
|
|
|
|
|
|
User story: as a workstation user, I want geth to start now and at future
|
|
|
|
|
logins without learning my platform's service-manager syntax.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth daemon install
|
|
|
|
|
geth wait daemon
|
|
|
|
|
geth status
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`daemon install` initializes the selected home if needed, installs and enables
|
2026-07-18 16:31:59 +02:00
|
|
|
a service for the current user, starts it, and waits for local control to become
|
|
|
|
|
ready. It never installs a system service. A binary launched from a Cargo target
|
|
|
|
|
or temporary directory is copied into the selected geth home first, preventing
|
|
|
|
|
later build cleanup from breaking the service. Common lifecycle operations are
|
|
|
|
|
direct:
|
2026-07-18 15:23:20 +02:00
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth daemon status
|
2026-07-18 16:31:59 +02:00
|
|
|
geth daemon logs
|
|
|
|
|
geth daemon logs --follow
|
2026-07-18 15:23:20 +02:00
|
|
|
geth daemon stop
|
|
|
|
|
geth daemon start
|
|
|
|
|
geth daemon uninstall
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The older `geth daemon service ...` family remains supported for scripts and
|
|
|
|
|
advanced options. In particular, `geth daemon service install` installs without
|
|
|
|
|
starting unless `--start` is supplied.
|
|
|
|
|
|
2026-07-18 16:31:59 +02:00
|
|
|
If readiness times out, inspect `geth daemon status` and `geth daemon logs`.
|
|
|
|
|
Use `daemon install --no-wait` only when another process owns readiness checks.
|
|
|
|
|
|
2026-07-18 15:23:20 +02:00
|
|
|
### Keep state but run in the foreground
|
|
|
|
|
|
|
|
|
|
User story: as a developer, I want persistent state and logs attached to my
|
|
|
|
|
terminal.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth init
|
|
|
|
|
geth daemon run
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Set `RUST_LOG=geth_node=debug` when more daemon diagnostics are useful. Use
|
|
|
|
|
`geth --home <dir> ...` to operate an isolated home without exporting an
|
|
|
|
|
environment variable.
|
|
|
|
|
|
2026-07-18 16:15:13 +02:00
|
|
|
## Inspect And Change Configuration
|
|
|
|
|
|
|
|
|
|
User story: as an operator, I want to find and validate the exact configuration
|
|
|
|
|
used by one geth home without guessing an OS-specific path or hand-editing
|
|
|
|
|
common boolean and interval settings.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth config path
|
|
|
|
|
geth config show
|
|
|
|
|
geth config set sync.live_sync_interval_ms 10000
|
|
|
|
|
geth config validate
|
|
|
|
|
geth daemon stop
|
|
|
|
|
geth daemon start
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`config show` reports built-in defaults when the file has not been created yet.
|
|
|
|
|
`config set` preserves unrelated TOML and comments and refuses to replace the
|
|
|
|
|
file if the complete prospective configuration is invalid. Success means
|
|
|
|
|
`config validate` identifies the selected path as valid. Configuration is
|
|
|
|
|
loaded at daemon startup, so restart the user service after changes.
|
|
|
|
|
|
2026-07-18 15:23:20 +02:00
|
|
|
## Establish An Owner Trust Root
|
|
|
|
|
|
|
|
|
|
User story: as the mesh owner, I want my first node rooted in an existing SSH
|
|
|
|
|
or hardware-backed OpenSSH admin key without copying that private key into
|
|
|
|
|
geth.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth init \
|
|
|
|
|
--admin-key ~/.ssh/id_ed25519_sk.pub \
|
|
|
|
|
--signing-key ~/.ssh/id_ed25519_sk \
|
|
|
|
|
--owner eric \
|
|
|
|
|
--node-name owner-laptop
|
|
|
|
|
geth daemon install
|
|
|
|
|
geth keychain status
|
|
|
|
|
geth node list
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The public key becomes an admin trust anchor. The private key or FIDO/YubiKey
|
|
|
|
|
stub is passed to `ssh-keygen -Y sign`; geth does not copy it into local state.
|
|
|
|
|
Success means `keychain status` reports accepted signed operations and `node
|
|
|
|
|
list` includes the named owner node.
|
|
|
|
|
|
|
|
|
|
## Enroll A Second Node
|
|
|
|
|
|
|
|
|
|
User story: as the owner, I want to approve a new device without treating
|
|
|
|
|
discovery or a peer card as proof of trust.
|
|
|
|
|
|
|
|
|
|
1. Export and transfer the owner's signed peer card:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth peer export --out owner.peer.json
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2. On the new node, initialize, import the card, and submit a request:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth init
|
|
|
|
|
geth daemon install
|
|
|
|
|
geth peer import owner.peer.json
|
|
|
|
|
geth node enroll request --node-name workstation --out workstation.enroll.json
|
|
|
|
|
geth node enroll submit owner-laptop --path workstation.enroll.json
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
3. On the owner node, review and approve with the admin key:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth node enroll list --status pending
|
|
|
|
|
geth node enroll approve <request-id> --signing-key ~/.ssh/id_ed25519_sk
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
4. On the new node, pull and inspect the approved state:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth sync now owner-laptop
|
|
|
|
|
geth wait sync owner-laptop
|
|
|
|
|
geth node list
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Peer-card import only supplies signed endpoint metadata. The owner-signed
|
|
|
|
|
keychain and authorization operations are what create trust and capabilities.
|
|
|
|
|
|
|
|
|
|
## Move A Blob Between Nodes
|
|
|
|
|
|
|
|
|
|
User story: as a mesh user, I want to address content by hash and let an
|
|
|
|
|
authorized node fetch it over Iroh.
|
|
|
|
|
|
|
|
|
|
On the provider:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth cas add ./archive.tar
|
|
|
|
|
geth node grant workstation resource:cas:local cas.fetch \
|
|
|
|
|
--signing-key ~/.ssh/id_ed25519_sk
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
On the consumer, after peer cards and grants have synchronized:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth cas fetch owner-laptop <blob-hash>
|
|
|
|
|
geth cas providers <blob-hash>
|
|
|
|
|
geth cas get <blob-hash> --out ./archive.tar
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Success means the fetch reports the provider, `cas providers` records it, and
|
|
|
|
|
the output hashes to the requested CAS hash. Remote fetch is Iroh-only and is
|
|
|
|
|
checked against `cas.fetch` on `resource:cas:local`.
|
|
|
|
|
|
|
|
|
|
## Synchronize Application State
|
|
|
|
|
|
|
|
|
|
User story: as a script author, I want small durable state primitives without
|
|
|
|
|
building transport, peer authentication, and retry handling myself.
|
|
|
|
|
|
|
|
|
|
Start locally with one of:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth kv create preferences
|
|
|
|
|
geth kv set preferences theme dark
|
|
|
|
|
|
|
|
|
|
geth document create settings
|
|
|
|
|
geth document set settings '{"theme":"dark"}'
|
|
|
|
|
|
|
|
|
|
geth db add inventory ./inventory.sqlite
|
|
|
|
|
|
|
|
|
|
geth cas root add notes ./notes
|
|
|
|
|
geth cas root scan notes
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Grant the matching resource capability to a node, then use the module's `sync`
|
|
|
|
|
command or `geth sync now <node>`. Check `geth sync status --json` for
|
|
|
|
|
per-peer/per-stream cursors and retry state. File-root application is
|
|
|
|
|
conservative: it does not overwrite local edits, and ambiguous changes become
|
|
|
|
|
durable conflicts for `geth cas conflict list`.
|
|
|
|
|
|
|
|
|
|
## Automate Reliably
|
|
|
|
|
|
|
|
|
|
User story: as an automation author, I want explicit homes, readiness checks,
|
|
|
|
|
machine-readable output, and stable errors.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth --home "$job_home" init
|
|
|
|
|
geth --home "$job_home" daemon run >"$job_home/daemon.log" 2>&1 &
|
|
|
|
|
daemon_pid=$!
|
|
|
|
|
geth --home "$job_home" wait daemon --timeout-ms 30000 --json
|
|
|
|
|
geth --home "$job_home" status --json
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Use `--json` for single responses and `--jsonl` for streaming responses. A
|
|
|
|
|
missing daemon returns the stable error code `daemon_unavailable` plus a startup
|
|
|
|
|
hint. See `automation-examples.md` and `command-stability.md` before depending
|
|
|
|
|
on experimental command families.
|
|
|
|
|
|
|
|
|
|
## Diagnose, Back Up, And Recover
|
|
|
|
|
|
|
|
|
|
User story: as an operator, I want actionable local diagnostics and a backup
|
|
|
|
|
that does not accidentally collect private trust anchors.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth doctor
|
|
|
|
|
geth status
|
|
|
|
|
geth sync status
|
|
|
|
|
geth backup create --out ./geth-backup
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`doctor` works even when the daemon is unavailable. Backups exclude daemon
|
|
|
|
|
runtime files, private geth identity keys, and external private SSH admin keys.
|
|
|
|
|
Restore always targets a separate empty home:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
geth backup restore ./geth-backup --target-home ./restored-geth
|
|
|
|
|
geth --home ./restored-geth daemon run
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Workflow Verification Coverage
|
|
|
|
|
|
|
|
|
|
- CLI tests cover help discoverability, `--home` selection, initialization,
|
|
|
|
|
daemon control, stable JSON errors, wait behavior, service-definition
|
|
|
|
|
generation, and the owner/enrollment/sync path.
|
|
|
|
|
- Two-daemon integration tests cover peer-card exchange, authorization denials,
|
|
|
|
|
signed log import, CAS/KV/document/DB/file-root sync, pipe/pubsub, and restart
|
|
|
|
|
behavior where practical.
|
|
|
|
|
- Real user-service managers, hardware keys, real relays, TUN/Wintun privileges,
|
|
|
|
|
and the full two-machine experience remain dogfood checks because automated
|
|
|
|
|
tests must not mutate host services or require privileged hardware.
|
|
|
|
|
|
|
|
|
|
The real-machine acceptance checklist is in `dogfood-checklist.md`.
|