DreamLake

Secrets, modes, tunnels, config, nymph

Part of the CLI examples cookbook. Auth setup lives on Auth + setup.

Secrets

Server-stored credentials referenced by providers, mounts, storage entries, and tunnels. Plaintext only flows on the way in — list and show return metadata.

--kind is required and must be one of ssh_key, aws_keypair, gcp_sa_json, or opaque.

secrets add — from a file

bash
lakeshore secrets add my-pem \
  --kind ssh_key \
  --from-file ~/.ssh/id_ed25519 \
  --description "primary dev key"

secrets add — from stdin

When --from-file is absent the CLI reads piped stdin, which keeps the plaintext off disk.

bash
pbpaste | lakeshore secrets add gcp-sa --kind gcp_sa_json          # macOS
cat ~/Downloads/sa.json | lakeshore secrets add gcp-sa --kind gcp_sa_json

secrets list / show — metadata only

bash
lakeshore secrets list
lakeshore secrets show my-pem

secrets rotate — replace the plaintext

Same input rules as add: --from-file, or piped stdin.

bash
lakeshore secrets rotate my-pem --from-file ~/.ssh/id_ed25519.new

secrets remove

bash
lakeshore secrets remove my-pem

Secrets are referenced elsewhere by the $secret marker — e.g. --kwarg 'creds.$secret=aws-prod-keys' on storage add and mounts add, or --creds aws-prod-keys as shorthand on storage add.

Modes

A mode is a server-stored RunConfig: a named compute target (provider, resources, tags). The Python API dispatches against modes; the CLI manages their definitions.

Modes use `--field`, not `--kwarg`

Every other group's inline override flag is --kwarg. modes add and modes update use --field. (The generated shell completion still advertises --kwarg here — that table is stale.)

modes add — from a file

bash
cat > /tmp/h100.yaml <<'YAML'
provider: my-ec2
resources:
  gpus: 1
  cpus: 8
  memory_gb: 64
tags:
  - gpu:h100
YAML
lakeshore modes add h100 --config-file /tmp/h100.yaml

modes add — inline field overrides

Dotted keys nest.

bash
lakeshore modes add cpu-small \
  --field provider=my-ec2 \
  --field resources.cpus=2 \
  --field resources.memory_gb=8

modes list / show / update / remove

update merges; =null drops a key.

bash
lakeshore modes list
lakeshore modes show h100

lakeshore modes update h100 --field resources.gpus=2
lakeshore modes update h100 --field tags=null
lakeshore modes update h100 --config-file /tmp/h100.yaml

lakeshore modes remove h100

Tunnels

WireGuard configs the control plane uses to reach providers behind a VPN. --kind defaults to wireguard, and wireguard is the only supported value.

tunnels add — from a config file

--config-file accepts .conf (wg-quick INI), .yaml, or .json.

bash
lakeshore tunnels add wg-vpc --config-file /tmp/wg-vpc.conf

tunnels add --conf — inline INI

bash
lakeshore tunnels add wg-vpc --conf "$(cat <<'INI'
[Interface]
PrivateKey = abc123=
Address    = 10.0.0.2/24

[Peer]
PublicKey  = peer-key=
Endpoint   = 1.2.3.4:51820
AllowedIPs = 10.0.0.0/24
INI
)"

tunnels list / show / remove

remove refuses while any provider still references the tunnel.

bash
lakeshore tunnels list
lakeshore tunnels list --json
lakeshore tunnels show wg-vpc --json
lakeshore tunnels remove wg-vpc

Attach a tunnel to a provider with providers update <name> --tunnel <tunnel> — see Providers and discover.

Nymph binaries

For rolling debug builds at a fleet without cutting an R2 release. Pair with daemon update --url. Both subcommands need an admin token — --admin-token, defaulting to $LAKESHORE_ADMIN_TOKEN.

nymph push — upload a binary

--target <triple> defaults to a value inferred from the ELF header's e_machine; --name <label> labels the upload.

bash
LAKESHORE_ADMIN_TOKEN=changeme \
  lakeshore nymph push ./target/x86_64-unknown-linux-gnu/release/nymph
✓ uploaded nymph (4.1 MB)
  sha256: 3f2a…
  label:  nymph
  target: x86_64-unknown-linux-gnu
  url:    /v1/admin/nymph-releases/3f2a…
  full:   http://localhost:8080/v1/admin/nymph-releases/3f2a…
`--json` emits a server-relative `url`

The url field in the --json envelope is a path, not an absolute URL. Daemons OTA from the fully-qualified address — the full: line in the human output. Prefix the server origin yourself when scripting.

nymph list — what's stored

bash
LAKESHORE_ADMIN_TOKEN=changeme lakeshore nymph list --json

Push and roll the fleet

bash
PUSH=$(LAKESHORE_ADMIN_TOKEN=changeme lakeshore nymph push ./nymph --json)
lakeshore daemon update --all \
  --url "$LAKESHORE_URL$(jq -r '.url' <<<"$PUSH")" \
  --sha256 "$(jq -r '.sha256' <<<"$PUSH")" \
  --yes
No `--update` glue yet

nymph push deliberately has no --update <daemon...> flag. Chain it to daemon update --url as above.

Config

Diagnostics for the resolved .dreamrc. None of the three subcommands take flags.

bash
lakeshore config show      # print the resolved DreamRc as YAML
lakeshore config source    # which source it came from
lakeshore config refresh   # force a server pull and update the on-disk cache

config source prints one of env, workspace, home, server, cache, or none, matching the resolution order (first hit wins):

  1. --dreamrc <path> — the CLI's one global option (reported as explicit).
  2. DREAMRC env var → env.
  3. ./.dreamrc, walking up from cwd → workspace.
  4. $HOME/.dreamrc → home.
  5. A server pull (needs auth or LAKESHORE_URL) → server.
  6. The on-disk cache from a previous pull → cache.
  7. Nothing — an empty DreamRc → none.

The server pull composes a DreamRc from the namespace's providers and modes, and caches it at $XDG_CACHE_HOME/lakeshore/<server-host>/<namespace>/dreamrc.yml (dir 0700, file 0600). If the pull fails, the CLI falls back to that cache and prints ⚠ server unreachable, using cached config from <ts>.

Three different config files

.dreamrc (providers + modes, YAML with !providers.<Kind> tags) is not the same as .lakeshore / .lakeshore.local (project defaults for daemon launch, a top-level daemon: block, walked up from cwd and stopped at the git root), and neither is lakeshore.yaml (the compose file for up / down / ps / status / logs, read from cwd only). See Configuration.

Completion

bash
echo 'eval "$(lakeshore completion bash)"' >> ~/.bashrc
echo 'eval "$(lakeshore completion zsh)"'  >> ~/.zshrc
lakeshore completion fish | source

Full details — the static tree, the dynamic __suggest callback, and the 30-second cache — at /cli/completion.

Read next