DreamLake

Host enrollment

dreamlake hosts enroll bootstraps a user-owned nymph over your existing SSH connection, then waits for the backend to confirm that exact enrollment online. Provider registration is not required. It requires the new authenticated Hosts API and a control plane supporting identity-bound grants and signed reconnect; these changes must be deployed together. --dry-run only validates inputs and does not contact the server or target.

The target needs Python 3, OpenSSL, an accessible systemd user manager, and user linger enabled for service persistence after logout. Enrollment never uses sudo. It reuses an installed nymph, or downloads the official installer into the user-local binary directory. --nymph-version selects an installer version when the binary is absent. The target generates and retains its nymph private key; only its public key and Unix username go to the enrollment API. Short-lived grants travel to the target over SSH stdin, not process arguments or logs.

Check the target account before enrollment:

shell
ssh bos14-ctrl 'systemctl --user show-environment >/dev/null && loginctl show-user "$(id -un)" -p Linger --value'

If this prints no, enable lingering for that account:

shell
ssh bos14-ctrl 'loginctl enable-linger "$(id -un)"'

If local policy denies this operation, ask the host administrator to enable it. Enrollment checks these prerequisites before creating an identity or requesting a grant.

Use --lakeshore-id when your namespace has multiple control-plane connections. The command prints a request ID before enrollment. After an interrupted request, repeat the same inputs with --request-id <id>. If the API returns retryAt, wait until that time before starting a new request. JSON errors retain the request ID and available operation/retry fields. --wait-seconds bounds readiness polling (default 60). A timeout reports pending and exits nonzero; it does not claim enrollment succeeded. Repeat execution preserves the target identity and reuses the user service. Runner/job readiness is a separate check from a connected nymph.

Direct enrollment on the target host is planned but has no implemented command syntax yet. For the broader workflow, see the upcoming host enrollment guide in the main DreamLake docs (not yet deployed). This page is the CLI input reference.

shell
dreamlake hosts enroll -p fortyfive/bos14 -n bos14-ctrl --ssh bos14-ctrl
dreamlake hosts status fortyfive/bos14/bos14-ctrl --json
dreamlake hosts status 'fortyfive/bos14/*' --json

For configuration-only validation:

shell
dreamlake hosts enroll -p fortyfive/bos14 -n bos14-ctrl \
  --ssh bos14-ctrl --dry-run

# Equivalent full name, with structured output:
dreamlake hosts enroll -n fortyfive/bos14/bos14-ctrl \
  --ssh '-i "/Users/ge/My Keys/key" \
    -J ge@bastion.example.com \
    -p 2222 geyang@bos14-ctrl.internal' --dry-run --json

Names have exactly three components: namespace/group/host. A matching explicit prefix and embedded prefix are accepted; conflicting prefixes and wildcards are rejected. Each component is 1–64 letters, digits, underscores or hyphens and starts with a letter or digit. A namespace in a name does not grant access to it. The control-plane namespace comes from the selected connection and can differ from the DreamLake namespace.

JSON input

shell
dreamlake hosts enroll --config ./bos14-host.json --dry-run --json
json
{
  "name": "fortyfive/bos14/bos14-ctrl",
  "ssh": {
    "host": "bos14-ctrl.internal",
    "user": "geyang",
    "port": 2222,
    "identityFile": "/Users/ge/.ssh/bos14_ed25519",
    "jumpHost": "ge@bastion.example.com",
    "options": { "ServerAliveInterval": "30" }
  }
}

The file may also contain prefix. Explicit CLI name/prefix fields override those file fields, then prefix conflicts are checked. --ssh replaces the entire file SSH object. Unknown fields are rejected. Identity files are local paths, never embedded key contents. Use either ssh.user or user@host, not both. --json controls output only.

SSH argument text is tokenized without shell expansion or evaluation; multiline whitespace, line continuations, and quoted paths are supported. Do not include ssh itself or a remote command. The initial supported flags are -i, -J, -p, -o, -l, and -F, each followed by a separate value. Supported -o settings are BatchMode, ServerAliveInterval, ServerAliveCountMax, ConnectTimeout, IdentitiesOnly, StrictHostKeyChecking, and UserKnownHostsFile. Use an existing SSH config alias for more advanced transport settings. Preview validates syntax, not whether an identity file exists, an SSH alias resolves, or SSH authentication works. Passwords are not accepted in arguments or JSON. Future interactive enrollment should let OpenSSH prompt for target/jump-host passwords locally; the preview does not attempt authentication and does not require agent forwarding.

Group status accepts --page (1–100000) and --page-size (1–100). Exact host lookup starts at the first page and follows matching pages automatically.

Host status is read from the backend; enrollment succeeds only when the returned enrollment ID reports online. Infrastructure provisioning and workload execution remain separate from this operation.

Optional cross-device SSH credential storage (preview only)

Enrollment initiated from your laptop uses your local SSH access. Normal operation through nymph does not require saved SSH credentials. To request future per-host vault access from your other devices, including mobile, opt in:

shell
dreamlake hosts enroll -n fortyfive/bos14/bos14-ctrl \
  --ssh '-i /Users/ge/.ssh/bos14_ed25519 bos14-ctrl' \
  --save-credentials --dry-run --json

Saving credentials does not authorize DreamLake backend services to initiate SSH connections. Any backend SSH delegation is a separate permission to design; this flag does not grant it. The vault access, encryption, recovery, and revocation mechanisms remain to be implemented.

This flag currently records intent only: output includes credentialSaveRequested: true, credentialsSaved: false, and a warnings array. Without the flag, credential saving is not requested. Human-readable warnings go to stderr. The preview does not read identity files, save, or upload credentials. Real enrollment with --save-credentials remains unsupported and exits nonzero before contacting the target; omit the flag for normal enrollment. Do not put private keys or passwords into configuration JSON. The flag is a CLI-only opt-in; it is not accepted as a configuration JSON field.

Cross-component integration check

The repository includes a repeatable check against an isolated local Hosts API, control plane, persistent databases, and a compiled nymph binary:

shell
pnpm build
node scripts/test-hosts-integration.mjs \
  /path/to/protected-test-environment.json /path/to/nymph

The protected JSON supplies remote, namespace, token, outsiderToken, and lakeshoreId; use test-only credentials and a loopback server. The test launches the actual CLI and nymph subprocesses, verifies online status, stable explicit request replay, consumed-token and token-absent reconnect, and forbidden access before target mutation. It uses local SSH/service adapters, so this is not a live-network SSH or actual-systemd test. Real target access and runner execution need their own acceptance checks. Test processes are stopped and temporary identity files removed afterward.