@fatagnus/remote-cmd-relay
v2.0.2
Published
CLI tool for executing commands on remote machines through a Convex backend
Maintainers
Readme
Remote Command Relay
A standalone binary that connects to Convex and executes commands on machines in restricted network segments. Features secure credential management, capability reporting, and real-time status updates.
Overview
The Remote Command Relay acts as a bridge between your Convex backend and machines that are not directly accessible from the internet. It:
- Authenticates with Convex using a Better Auth API key
- Reports capabilities (SSH, local commands, performance metrics)
- Maintains local credential store with AES-256-GCM encryption
- Reports credential inventory to center (metadata only, values stay local)
- Collects performance metrics (CPU, memory, disk)
- Polls for commands and executes them locally or via SSH
- Reports results back to Convex in real-time
Installation
Via npx (Recommended)
Run directly without installing:
npx @fatagnus/remote-cmd-relay --helpVia npm (Global Install)
npm install -g @fatagnus/remote-cmd-relay
remote-cmd-relay --helpPre-built Binaries
Download the pre-built binary for your platform from the GitHub Releases page.
| Platform | Binary Name |
|----------|-------------|
| Linux x86_64 | remote-cmd-relay_linux_amd64 |
| Linux ARM64 | remote-cmd-relay_linux_arm64 |
| macOS Intel | remote-cmd-relay_darwin_amd64 |
| macOS Apple Silicon | remote-cmd-relay_darwin_arm64 |
# Example: Download and run on Linux x86_64
curl -L -o remote-cmd-relay https://github.com/ozanturksever/remote-cmd-relay/releases/latest/download/remote-cmd-relay_linux_amd64
chmod +x remote-cmd-relay
./remote-cmd-relay --helpBuild from Source
cd packages/cli
bun install
bun run build:npm # Build npm package
bun run build:binaries # Build standalone binaries for all platformsUsage
./remote-cmd-relay <API_KEY> <CONVEX_URL> [options]Arguments
| Argument | Description |
|----------|-------------|
| API_KEY | Better Auth API key for authentication |
| CONVEX_URL | Convex site URL (e.g., https://your-app.convex.site) |
Options
| Option | Description | Default |
|--------|-------------|---------|
| --poll-interval <ms> | Command polling interval | 5000 |
| --heartbeat-interval <ms> | Heartbeat/status report interval | 30000 |
| --log-level <level> | Log level: debug, info, warn, error | info |
| --store-dir <path> | Custom directory for credential store | ~/.remote-cmd-relay |
| --deployment-url <url> | Convex deployment URL for subscription mode | - |
| --component-name <name> | Convex component name | remoteCmdRelay |
| --help, -h | Show help message | - |
| --version, -v | Show version | - |
Examples
# Basic usage
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site
# With debug logging
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site --log-level debug
# With faster polling (2 seconds)
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site --poll-interval 2000
# With more frequent heartbeats (10 seconds)
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site --heartbeat-interval 10000
# Subscription mode for real-time RPC (recommended for low latency)
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site \
--deployment-url https://my-app.convex.cloudFeatures
Capability Detection
On startup, the relay detects and reports its capabilities:
| Capability | Description |
|------------|-------------|
| ssh | Can execute commands on remote machines via SSH |
| local_cmd | Can execute commands locally on the relay host |
| perf_metrics | Can collect and report performance metrics |
Credential Management
The relay maintains an encrypted local credential store:
- Location:
~/.remote-cmd-relay/credentials.enc - Encryption: AES-256-GCM
- Key derivation: PBKDF2 with 100,000 iterations
- Key material: API key + machine ID + local salt
Credential Types
| Type | Description |
|------|-------------|
| ssh_key | SSH private key for remote access |
| password | Password credential |
| api_key | API key for services |
Storage Modes
| Mode | Description |
|------|-------------|
| relay_only | Credential stored only on relay (most secure) |
| shared | Credential can be backed up to center (for recovery) |
Performance Metrics
The relay collects and reports system metrics:
- CPU: Usage percentage
- Memory: Usage percentage, used/total MB
- Disk: Usage percentage, used/total GB
- Load Average: 1m, 5m, 15m averages
Status Reporting
The relay reports its status to the center:
- Capabilities
- Performance metrics
- Credential inventory (names only, not values)
- Version, hostname, platform info
- Last heartbeat timestamp
Setup Guide
1. Create an API Key
In the relay management UI or programmatically:
const { key } = await authClient.apiKey.create({
name: "production-relay",
});
// Save this key - it won't be shown again!2. Create a Relay Assignment
Link the API key to a machine:
await createAssignment({
apiKeyId: apiKey.id,
machineId: machine._id,
name: "Production Server Relay",
createdBy: userId,
});3. Deploy and Run the Relay
# Copy binary to target machine
scp dist/remote-cmd-relay user@server:/opt/relay/
# Run the relay
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site4. Add Credentials (Optional)
For SSH access to other machines, add credentials to the relay's local store. Credentials can be managed via the center UI or pushed from center for shared credentials.
5. Queue Commands
From your application:
// Local command
await queueCommand({
machineId: machine._id,
command: "df -h",
targetType: "local",
timeoutMs: 30000,
createdBy: userId,
});
// SSH command to another machine
await queueCommand({
machineId: machine._id,
command: "systemctl status nginx",
targetType: "ssh",
targetHost: "192.168.1.100",
targetPort: 22,
targetUsername: "admin",
timeoutMs: 30000,
createdBy: userId,
});Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ CONVEX CENTER │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │
│ │ Assignments │ │ Commands │ │ Status │ │ Credentials│ │
│ │ Table │ │ Queue │ │ Table │ │ Inventory │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └────────────┘ │
└────────────────────────────┬────────────────────────────────────────┘
│ HTTPS
│
┌────────────────────────────▼────────────────────────────────────────┐
│ RELAY BINARY │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │
│ │ Capability │ │ Command │ │ Status │ │ Credential │ │
│ │ Detection │ │ Executor │ │ Reporter │ │ Store │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Metrics │ │ Sync │ │
│ │ Collector │ │ Manager │ │
│ └─────────────┘ └─────────────┘ │
└────────────────────────────┬────────────────────────────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
┌───────▼───────┐ ┌────▼────┐ ┌──────▼──────┐
│ Local Exec │ │ SSH │ │ Metrics │
│ (this machine)│ │ Exec │ │ Collection │
└───────────────┘ └─────────┘ └─────────────┘Security
Authentication
- API keys are validated on every request
- Keys are managed via Better Auth with hashing and expiration
Credential Storage
- Local credentials encrypted with AES-256-GCM
- Encryption key derived from API key + machine ID
relay_onlycredentials never leave the relay
Command Execution
- Commands validated against whitelist (configurable)
- SSH uses private key authentication
- Each relay only processes commands for its assigned machine
Operating Modes
Polling Mode (Default)
The relay polls the Convex backend at regular intervals (default: 5 seconds) to check for pending commands. This is simple and works everywhere but has higher latency.
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.siteSubscription Mode (Recommended for RPC)
The relay maintains a WebSocket connection to Convex and receives commands instantly via subscriptions. This enables sub-second latency for RPC-style command execution.
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site \
--deployment-url https://my-app.convex.cloudWhen to use subscription mode:
- When using the
exec()helper in Convex actions - When you need synchronous command execution
- When low latency is important
Note: The --deployment-url should be your Convex deployment URL (ending in .convex.cloud), not your site URL (ending in .convex.site).
Network Security
- All communication over HTTPS
- Relay initiates connections (no inbound ports required)
- Suitable for firewalled/NAT environments
Troubleshooting
Relay not connecting
# Check with debug logging
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site --log-level debugSSH commands failing
- Verify credentials are stored: check
~/.remote-cmd-relay/credentials.encexists - Check the relay has SSH capability reported
- Verify target host is reachable from relay
High CPU/Memory usage
Increase polling interval:
./remote-cmd-relay sk_live_xxxxx https://my-app.convex.site --poll-interval 10000Development
# Install dependencies
bun install
# Run in development mode
bun run dev sk_live_xxxxx https://my-app.convex.site --log-level debug
# Build
bun run build
# Type check
bun run typecheckFiles
| File | Description |
|------|-------------|
| index.ts | CLI entry point and argument parsing |
| relay.ts | Main relay logic and coordination |
| executor.ts | Local and SSH command execution |
| credentials.ts | Encrypted credential store |
| capabilities.ts | Capability detection |
| metrics.ts | Performance metrics collection |
| sync.ts | Config/credential sync with center |
| logger.ts | Timestamped logging utility |
License
MIT
