Reference

Step SSH (:ssh)

Quick Answer

Use this reference for running remote commands over SSH.

  • Sync: the flow pauses until the remote command exits (or times out).
  • Async agent pattern: kick off a long-running job over SSH, then use a :wait callback to resume later (see Remote Agents (SSH)).
  • VM setup: if you need to provision the host and wire secrets from scratch, start with Set Up A VPS Or VM For Breyta SSH.
  • Important: treat sync :ssh as short-task execution. For long-running or output-silent jobs, use async kickoff + callback wait.
  • Testing: local mock mode + real-SSH walkthrough (see SSH Testing).

Canonical Shape

Core fields:

FieldTypeRequiredNotes
:connectionkeyword/stringYesSlot name (preferred) or connection id
:commandstringYesShell command executed via sh -lc on the remote host
:workdirstringNoRuns cd <workdir> && ... before the command
:envmapNoEnvironment variables passed to the command
:stdinstringNoBytes written to the remote process stdin
:pty?booleanNoAllocate a PTY (for interactive commands/tools)
:timeoutintNoCommand timeout seconds (default 60)
:connect-timeout-msintNoConnection timeout in milliseconds
:max-output-bytesintNoCombined stdout+stderr cap (bounded by server limits)
:ok-exit-codesvectorNoAllowed exit codes (default [0])
:log-command-preview?booleanNoIf true, logs a short command preview (avoid secrets)

Success result (when exit code is allowed):

{:success true
 :exit 0
 :stdout "..."
 :stderr "..."
 :duration-ms 123}

If the command exits with a disallowed exit code, the step fails and surfaces a structured error including the exit code and a stderr preview.

SSH Connection (:type ssh, :backend ssh)

The :ssh step expects an SSH connection with connection config like:

{
  "host": "example.com",
  "port": 22,
  "username": "ubuntu",
  "auth": {
    "type": "private-key",
    "secret-ref": "ssh-private-key",
    "passphrase-secret-ref": "ssh-key-passphrase"
  },
  "known-hosts": { "secret-ref": "ssh-known-hosts" }
}

Auth:

  • auth.type supports private-key and password.
  • secret-ref values are fetched from the workspace secret-store at runtime.

Host key verification:

  • Prefer known-hosts (a secret containing OpenSSH known_hosts content).
  • Dev-only escape hatch: set insecure-skip-host-key-verification: true on the connection config.

Local simulation (no network):

  • Set mode: "mock" on the connection config. The step returns a deterministic mock result.

Limits And Behavior

  • The remote command is executed as: sh -lc "<script>".
  • Output is bounded by :max-output-bytes across stdout + stderr; exceeding the cap fails the step.
  • :env keys must be valid env var names (FOO, MY_VAR_1).
  • In production-like environments, hosts that resolve to private IPs are blocked by default to reduce SSRF risk.
  • Long sync SSH jobs are not the recommended execution model for agent-style work; workflow activity runtime limits can terminate the step before remote completion. Use the async agent pattern for jobs that can run several minutes or more.

Canonical Examples

Sync exec

'(let [res (flow/step :ssh :exec
                      {:type :ssh
                       :title "Run remote command"
                       :connection :vps
                       :command "echo hello; uname -a"
                       :timeout 60})]
   res)

Async agent kickoff + callback wait

See: Remote Agents (SSH).

Related

As of Mar 13, 2026