Commands Server
Run nodes in different servers via Cap’n Proto RPC.
Quick start
Use spo
CLI to generate a simple config with your API key and run below command inside flow-backend repository:
$ spo run all-cmds-server
Your servers will be used to run nodes in your flows.
Example output:
🚀 > spo run all-cmds-server 09:56:56 AM
generated _data/all-cmds-server.jsonc
$ cargo build --bin all-cmds-server
warning: use of deprecated trait `solana_program::program_error::PrintProgramError`: Use `ToStr` instead with `solana_msg::msg!` or any other logging
--> vendor/mpl-token-metadata/src/generated/errors/mpl_token_metadata.rs:624:37
|
624 | impl solana_program::program_error::PrintProgramError for MplTokenMetadataError {
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
warning: `mpl-token-metadata` (lib) generated 1 warning
Finished `dev` profile [optimized] target(s) in 0.36s
$ target/debug/all-cmds-server _data/all-cmds-server.jsonc
2025-10-13T02:57:04.677085Z INFO command_rpc::command_side::command_server: using public key: c279c19826915ed6c303bd0895e236d0d6d6950f562195a14edaf3a7bf29708b
2025-10-13T02:57:08.470314Z INFO command_rpc::command_side::command_server: joined 12b5b06f4837f4998f24186fc013a066c5e00f56750bc72028a53f3d0c8335cd
2025-10-13T02:57:08.470341Z INFO command_rpc::command_side::command_server: connection type Some(Direct(34.169.65.3:1536))
2025-10-13T03:04:33.779756Z INFO command_rpc::command_side::command_trait: ran generate_keypair 190.430925ms
2025-10-13T03:04:34.806439Z INFO command_rpc::command_side::command_trait: ran wallet 190.432655ms
2025-10-13T03:04:34.806837Z INFO command_rpc::command_side::command_trait: ran const 190.776821ms
2025-10-13T03:04:34.806965Z INFO command_rpc::command_side::command_trait: ran generate_keypair 190.8822ms
What happened:
The CLI generated
_data/all-cmds-server.jsonc
because it didn't existBuild the binary with
cargo build --bin all-cmds-server
Running
all-cmds-server
with generated generated config:target/debug/all-cmds-server _data/all-cmds-server.jsonc
When you start your flow, nodes will be automatically run on your node server:
2025-10-13T03:04:33.779756Z INFO command_rpc::command_side::command_trait: ran generate_keypair 190.430925ms 2025-10-13T03:04:34.806439Z INFO command_rpc::command_side::command_trait: ran wallet 190.432655ms 2025-10-13T03:04:34.806837Z INFO command_rpc::command_side::command_trait: ran const 190.776821ms 2025-10-13T03:04:34.806965Z INFO command_rpc::command_side::command_trait: ran generate_keypair 190.8822ms
To stop the server, press CTRL+C.
Configuration
Config files are written in JSONC format. Config schema: https://schema.spaceoperator.com/command-server-config.schema.json , you can include this schema in the file to use IDE auto-complete (not required).
Top-Level Properties
The root of the configuration is a JSON object with the following properties:
flow_server
flow_server
Type:
array
ofFlowServerConfig
objectsRequired: No
Description: A list of flow servers the command server should connect to. This is the primary way to define upstream servers.
Default: If this property is not specified, the server will default to connecting to our main server
https://dev-api.spaceoperator.com/
. The default value is:[ { "url": "https://dev-api.spaceoperator.com/" } ]
secret_key
secret_key
Type:
string
Required: No
Description: The Iroh secret key that determines the server's unique node ID. Providing a key ensures the server has the same identity across restarts. If not specified, a new key (and thus a new node ID) will be generated every time the server starts.
apikey
apikey
Type:
string
Required: No
Description: A global API key used to authenticate with all servers defined in the
flow_server
list. This is a convenient way to set authentication if all your flow servers share the same key. This key will be overridden by anyapikey
specified within an individualFlowServerConfig
object.
Object Definitions
These are the definitions of complex objects that can be used within the configuration.
FlowServerConfig
FlowServerConfig
Each item in the flow_server
array is a FlowServerConfig
object. It defines a single flow server connection and can be specified in one of two ways: by public URL (FlowServerUrl
) or by direct node address (FlowServerAddress
).
It also has one optional common property:
apikey
(string
): An API key specific to this server entry. If provided, it overrides the globalapikey
for this specific connection.
Connection Methods
A FlowServerConfig
object must match one of the following structures:
FlowServerUrl
: Connect via a public URL.FlowServerAddress
: Connect directly via a node's specific address details.
FlowServerUrl
FlowServerUrl
This is the simplest and most common way to connect to a flow server.
url
string
(uri)
The public URL of the flow-server API.
Example:
{
"url": "https://dev-api.spaceoperator.com/"
}
FlowServerAddress
FlowServerAddress
This method is used for connecting directly to a node, bypassing a public-facing URL. This is an advanced option typically used when you know the node's direct network address details.
node_id
string
The unique Iroh node ID of the flow server.
Yes
relay_url
string
(uri)
The URL of the relay server used to help establish the connection.
Yes
direct_addresses
array
of string
An optional list of IP addresses (e.g., 192.168.1.10
) of the node.
No
Example:
{
"$schema": "https://schema.spaceoperator.com/command-server-config.schema.json",
"node_id": "b3af5dca5c351e1e...",
"relay_url": "https://use1-1.relay.n0.iroh.iroh.link./",
"direct_addresses": [
"10.0.0.5"
]
}
Full Configuration Examples
Specifying a Secret Key and a Custom Server
This configuration provides a persistent identity for the command server and connects it to a production flow server.
{
"$schema": "https://schema.spaceoperator.com/command-server-config.schema.json",
"secret_key": "my-super-secret-persistent-key-string",
"flow_server": [
{
"url": "https://dev-api.spaceoperator.com/"
}
]
}
Using a Global API Key for Multiple Servers
{
"$schema": "https://schema.spaceoperator.com/command-server-config.schema.json",
"secret_key": "my-super-secret-persistent-key-string",
"apikey": "global-api-key-for-all-servers",
"flow_server": [
{
"url": "https://dev-api.spaceoperator.com/"
},
{
"url": "http://localhost:8080/"
}
]
}
Using Per-Server API Keys
This example demonstrates how a specific server's apikey
overrides the global one.
{
"$schema": "https://schema.spaceoperator.com/command-server-config.schema.json",
"secret_key": "my-super-secret-persistent-key-string",
"flow_server": [
{
"url": "https://dev-api.spaceoperator.com/",
"apikey": "<API key for spaceoperator>"
},
{
"url": "http://api.mysite.com/"
"apikey": "<API key for your self hosted instance>"
}
]
}
Using the Advanced FlowServerAddress
Connection
FlowServerAddress
ConnectionThis configuration connects to one server via its URL and to another via its direct node address details.
{
"$schema": "https://schema.spaceoperator.com/command-server-config.schema.json",
"secret_key": "my-super-secret-persistent-key-string",
"flow_server": [
{
"url": "https://dev-api.spaceoperator.com/",
"apikey": "<API key>"
},
{
"node_id": "b3af5dca5c351e1e0000ffffffffffffffffffffffffffff",
"relay_url": "https://use1-1.relay.n0.iroh.iroh.link./",
"direct_addresses": ["192.168.1.50"],
"apikey": "internal-node-key"
}
]
}
Last updated
Was this helpful?