Module remote: remote machine management
🔵 Module remote maintains a machine inventory and gives agents limited access
to them over SSH/SCP: host listing, command execution, file transfer, and
availability checks — under a per-machine policy. Private keys are not stored in
the inventory and never appear in API responses.
The module is part of the standard distribution (config/modules.enabled → remote).
51.1 Inventory
A machine is described by a document: slug, host, port, user, tags, the
authentication method, and the policy. The inventory lives in DuckDB (logs/machines.db) and
is seeded from config/remote/machines.yaml: when the DB is first opened, records
from the file are added if a machine with that slug does not yet exist. Edits made via
the API/tools are saved to the DB and are not overwritten on redeploy.
# config/remote/machines.yaml
machines:
- slug: web-1
host: 10.0.0.10
user: deploy
tags: [prod, web]
known_hosts: accept_new # strict | accept_new | insecure
auth:
type: key_secret # agent | key_file | key_secret | password_secret
name: WEB1_SSH_KEY
policy:
mode: allowlist # deny | readonly | allowlist | full
allow: ["uptime", "systemctl status *", "df -h"]
deny: ["rm -rf *"]
require_approval: false
The path to the DB and to the seed are overridden by the AGENT_OS_REMOTE_DB and
AGENT_OS_REMOTE_MACHINES variables.
51.2 Execution policy {#policy}
policy.mode defines what is allowed to be done on a machine:
| Mode | Behavior |
|---|---|
deny (default) |
execution forbidden, inventory only |
readonly |
only commands from allow (the same check as allowlist; the name documents the intent) |
allowlist |
only commands from allow |
full |
everything except commands from deny |
allow/deny — patterns with * and ? (full match of the command string). deny
always takes precedence over allow. Under require_approval: true, the call must pass
approved: true — otherwise the agent will not execute the command until it receives explicit
consent.
By default a machine is in deny mode — fail-closed: until a policy is set,
the machine is available only as an inventory record. Files (ssh_upload/ssh_download)
are allowed only under mode: full.
51.3 Authentication
auth.type |
What it is |
|---|---|
agent |
local ssh-agent / ~/.ssh/config (default) |
key_file |
path to a private key on disk (~ supported) |
key_secret |
private key stored in secrets under the name name |
password_secret |
password in secrets (password SSH is not yet supported in the runner) |
Named credentials are read through the host port agent_os.Secrets (name allowlist),
so the module declares the agent_os.Secrets capability. Secret references are taken
from both the YAML seed and DB records — both inventory entry points are equivalent.
51.4 Tools
The module adds 8 kinds of tools (see Tool Reference):
kind |
Purpose |
|---|---|
machine_list |
list machines (opt. filter tag) |
machine_get |
a single machine by slug |
machine_upsert |
create/update a machine |
machine_delete |
delete a machine |
ssh_exec |
execute a command on a machine |
ssh_upload |
upload a file to a machine (SCP) |
ssh_download |
download a file from a machine (SCP) |
remote_health |
availability check |
Example:
kind: ssh_exec
name: run_on_machine
description: Выполнить команду на управляемой машине
51.5 HTTP API
Inventory admin API (behind admin authentication, see HTTP API):
| Endpoint | Description |
|---|---|
GET /v1/machines |
list machines 🔒 |
POST /v1/machines |
create/update a machine (body — document) 🔒 |
GET /v1/machines/:slug |
a single machine 🔒 |
PUT /v1/machines/:slug |
update a machine (slug from the path) 🔒 |
DELETE /v1/machines/:slug |
delete a machine 🔒 |
Responses use the "redacted" representation of a machine (redacted()): the secret
name and keys are never disclosed.
51.6 Security
- Execution — shell-out to the system
ssh/scpwithBatchMode=yes,ConnectTimeout=15, keepalive, and host-key verification (known_hosts). - Commands are checked by the policy before launch;
denytakes priority. - Keys are not stored in the inventory; secrets are read via
agent_os.Secrets. - A key from a secret is materialized into a temporary file with
0600permissions.
51.7 Testing locally
Like any tool, the engine can be run without a server:
AGENT_OS_REMOTE_MACHINES=config/remote/machines.yaml \
AGENT_OS_REMOTE_DB=/tmp/machines.db \
./bin/agent-os tool config/agents/<agent>/tools/<tool>.yaml '{"slug":"web-1","command":"uptime"}'
51.8 Limitations
- Linked module only (DLL — later).
- Password authentication is not wired up (askpass is needed).
- The REST API covers the inventory; command execution for agents is available via tools (synchronous routes do not block on SSH).
- No background health polling (planned via
agent_os.Tasks).