Devices

Add an SSH connection

Save encrypted password or private-key authentication for a Linux or macOS host. Does not connect yet. Explicit host-access consent and a non-secret idempotency_key are required. Same key/body replays for 24 hours, including after credential rotation. Changed bodies, expired keys and deleted connections conflict. Keep credentials in a caller-side secret manager, never prompts or command history. REST only. Requires an API key with ssh:write, which is never granted by default: select it explicitly when creating the key.

Server setup requirements

Reason's hosted connector initiates SSH from Reason's cloud, not from your browser or computer. Configure the server before saving a connection:

  1. Use a Linux server or a Mac (macOS on Apple silicon or Intel) with an x64 or arm64 CPU. Windows is not supported by this automatic installation flow. SSH devices run headlessly; they do not provide desktop streaming or interactive desktop control.
  2. Provide a public hostname or IP address and an SSH port reachable from Reason's cloud. Private LAN, localhost, and Tailscale-only addresses are not supported, so a Mac or server behind a home router needs a public address or port forward. A successful SSH connection from your own computer does not prove cloud reachability. Reason may connect from more than one address. Configure the host's firewall and any upstream network rules according to your organization's security policy; do not disable the firewall.
  3. Enable SSH and authorize the supplied SSH user with a password or private key. Prefer a dedicated, least-privileged account and key. The account needs a private, writable home directory, disk space for the worker, and permission to read, write, and execute within its workspace. Root or administrator access is not required.
  4. Allow outbound HTTPS for the CLI download and the worker's connection to Reason. On Linux, the host needs bash, curl, getent, stat, readlink, and timeout. With systemd, a non-root user needs lingering enabled by the administrator. Without systemd, use Reconnect after the host restarts or the worker stops; such a worker also does not update itself, and Reconnect installs the current release. On macOS, the stock system tools are sufficient and the account does not need to sign in to the desktop. The worker runs as a per-user launchd agent, so use Reconnect after the Mac restarts, and keep the Mac from sleeping while it should accept work. With systemd or launchd, the worker checks for a new Reason release every six hours and restarts on it after finishing its current work.
  5. Save the connection, then connect to probe the SSH host key. Compare the fingerprint with a trusted source before choosing Trust & install, for example by running ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub on the host through a console you already trust. Reason installs and enrolls the worker only after that verification.

For example, an administrator can prepare a dedicated user on a systemd host, replacing the public key:

sudo useradd -m -s /bin/bash reason
sudo loginctl enable-linger reason
sudo install -d -m 700 -o reason -g reason /home/reason/.ssh
echo 'ssh-ed25519 AAAA... reason' | sudo tee /home/reason/.ssh/authorized_keys
sudo chown reason:reason /home/reason/.ssh/authorized_keys
sudo chmod 600 /home/reason/.ssh/authorized_keys

On a Mac, turn on Remote Login in System Settings > General > Sharing. Then an administrator can prepare the account from Terminal, replacing the public key. The dseditgroup line is needed only when Remote Login allows only specific users:

sudo sysadminctl -addUser reason -fullName "Reason worker" -password "$(openssl rand -base64 24)"
sudo createhomedir -c -u reason
sudo dseditgroup -o edit -a reason -t user com.apple.access_ssh
sudo -u reason install -d -m 700 /Users/reason/.ssh
echo 'ssh-ed25519 AAAA... reason' | sudo -u reason tee /Users/reason/.ssh/authorized_keys
sudo -u reason chmod 600 /Users/reason/.ssh/authorized_keys
sudo pmset -a sleep 0

Run a Session on the host

Once the connection is connected, its device_id is the enrolled Device (a different ID from the connection). Read GET /v3/organizations/{orgId}/devices/{device_id} and use a root's id as root_id, then create a Session with devices:use:

POST /v3/organizations/{orgId}/sessions
{
  "prompt": "Write fizzbuzz.py in the workspace, run it with python3, and report its output and df -h .",
  "idempotency_key": "<uuid>",
  "target": { "kind": "headless", "device_id": "<device_id>", "root_id": "<root_id>" }
}

GET the Session to read back its target.

Remove the host software

Deleting a connection deletes its credentials and revokes its Device; the worker files stay on the host. To remove them, run if [ "$(uname -s)" = Darwin ]; then for label in com.reasonmachines.ssh-updater.<connection_id> com.reasonmachines.ssh-worker.<connection_id> so.reason.ssh-updater.<connection_id> so.reason.ssh-worker.<connection_id> so.ara.ssh-updater.<connection_id> so.ara.ssh-worker.<connection_id>; do launchctl bootout user/$(id -u)/$label 2>/dev/null; rm -f ~/Library/LaunchAgents/$label.plist; done; else systemctl --user disable --now reason-ssh-<connection_id>-update.timer; systemctl --user disable --now reason-ssh-<connection_id>.service; rm -f ~/.config/systemd/user/reason-ssh-<connection_id>.service ~/.config/systemd/user/reason-ssh-<connection_id>-update.service ~/.config/systemd/user/reason-ssh-<connection_id>-update.timer; systemctl --user daemon-reload; fi; rm -rf ~/.reason-ssh/<connection_id> as the SSH user. For root, use systemctl without --user and the units in /etc/systemd/system. The workspace is left in place: by default the shared ~/.reason/workspace, which other Reason workers on the host also use.

If setup fails, inspect the connection's error_code: ssh_host_blocked means the address is not permitted; ssh_dns_failed means name resolution failed; ssh_authentication_failed means the credentials were rejected; ssh_platform_unsupported means the operating system or architecture is unsupported. A connected setup receipt is not proof that the Device remains online; check its current Device status.

<sub>Scope: ssh:write</sub>

post/v3/organizations/{orgId}/ssh-connections

Request

  • Base URL: https://api.reasonmachines.com
  • URL: https://api.reasonmachines.com/v3/organizations/{orgId}/ssh-connections
  • Auth: HTTP bearer

Request body

namestring required
hoststring required
portinteger
usernamestring required

SSH username, up to 64 characters, or Railway's sbx:<environment UUID>:<sandbox UUID> routing selector.

workspace_pathstring

Optional absolute remote workspace path. Omit to use the installer's private default workspace.

consent_host_accesstrue required
idempotency_keystring required

Persist one non-secret key per logical request. Retry the identical body/key for up to 24 hours. Expired or deleted request keys return 409; reconnect intentionally with a fresh key.

Response

Original saved receipt replayed.

replayedboolean required

Changes

No recorded changes to this operation across all 1 revision of this API.