Command Execution
OSAPI can execute arbitrary commands on managed hosts. Command execution runs through the job system, so the API server never runs commands directly -- agents handle all execution.
What It Does
| Operation | Description |
|---|---|
| Exec | Run a command directly without a shell interpreter |
| Shell | Run a command through /bin/sh -c with shell features |
Exec invokes the command binary directly with an explicit argument list. No
shell interpretation occurs, so metacharacters like |, >, and * are passed
literally. This is the safer option for structured automation.
Shell passes the command string to /bin/sh -c, enabling pipes, redirects,
variable expansion, and other shell features. Use this for ad-hoc debugging or
when you need shell syntax.
Both operations support a configurable working directory and a timeout (default 30 seconds, maximum 300 seconds). Results include stdout, stderr, the exit code, and execution duration.
How It Works
Command execution follows the same request flow as all OSAPI operations:
- The CLI (or API client) posts a request to the API server.
- The API server creates a job and publishes it to NATS.
- An agent picks up the job, executes the command, and writes the result back to NATS KV.
- The API server collects the result and returns it to the client.
You can target a specific host, broadcast to all hosts with _all, or route by
label. See CLI Reference for
usage and examples, or the
API Reference for the REST
endpoints.
Fact References
Command arguments support @fact.* references that resolve to live system
values on the executing agent. This is especially useful with broadcast
targeting, where each agent substitutes its own values:
$ osapi client node command exec \
--command ip --args "addr,show,dev,@fact.interface.primary" \
--target _all
See System Facts for the full list of available references.
Use Cases
- Ad-hoc debugging -- quickly check a process table, inspect a log file, or verify a configuration on a remote host without SSH.
- Automation fallback -- run a one-off command that does not yet have a dedicated OSAPI endpoint.
- Fleet-wide checks -- broadcast a command to all hosts to verify a package version, check disk space, or confirm a service is running.
Security Model
Command execution is a privileged operation, split into two permissions so a role can be scoped to structured commands without also granting shell access:
command:executeguards theexecendpoint (no shell interpretation).command:shellguards theshellendpoint (/bin/sh -c, with pipes, redirects, and expansion).
Only the built-in admin role includes either permission by default. The
write and read roles do not.
Upgrading? A custom role or token that was granted only
command:executeno longer reaches theshellendpoint -- it now also needscommand:shell. Addcommand:shellto any custom role or token that should keep shell access.
To grant command execution to a custom role:
controller:
api:
security:
roles:
ops:
permissions:
- command:execute
- command:shell
- node:read
- health:read
Or grant it directly on a token:
osapi token generate -r read -u user@example.com \
-p command:execute -p command:shell
Configuration
Command execution uses the general job infrastructure. No domain-specific configuration is required. See Configuration for NATS, agent, and authentication settings.
Permissions
| Operation | Permission |
|---|---|
| Exec | command:execute |
| Shell | command:shell |
Only the admin role includes command:execute or command:shell by default.
Grant them to other roles or tokens explicitly when needed.
Related
- CLI Reference -- command execution commands (exec, shell)
- System Facts -- available
@fact.*references - API Reference -- REST API documentation
- Job System -- how async job processing works
- Authentication & RBAC -- permissions and roles
- Architecture -- system design overview