Remote Deployment

🚧 Under Development: Remote deployment is currently under active development. Features and APIs may change. Check back for updates!

Note: Remote deployment requires horus_daemon running on the target robot. Local execution works immediately.

Deploy your HORUS applications to physical robots, edge devices, and remote hardware over the network. Build locally, run remotely with a single command.

Overview

Remote deployment allows you to:

  • Deploy to robots - Run code on physical hardware from your dev machine
  • Cross-compile - Build for different architectures (ARM, x86_64)
  • Monitor remotely - View logs and metrics over network
  • Hot reload - Update code without physical access
  • Manage fleets - Deploy to multiple robots simultaneously

Architecture:

─────────────────────────────────────────────────────────
 Dev Machine                          Robot            
                                                       
 horus run       ──── WiFi/LAN ──── horus_daemon      
 --remote robot        HTTP                            
                                      Builds & Runs    
─────────────────────────────────────────────────────────

Quick Start

On Robot (One-Time Setup)

# 1. Install HORUS
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
git clone <horus-repo>
cd HORUS
./install.sh

# 2. Start daemon
horus_daemon --port 8080

Output:

HORUS Daemon v0.1.0
Listening on: 0.0.0.0:8080
Ready for deployments

From Dev Machine

# Deploy to robot
horus run --remote 192.168.1.100:8080 --release

What happens:

  1. Packages project as tarball
  2. Uploads to robot via HTTP POST
  3. Robot builds code
  4. Robot runs executable
  5. Streams logs back to your terminal

Daemon Setup

Starting the Daemon

Basic:

horus_daemon

With options:

horus_daemon \
  --port 8080 \
  --host 0.0.0.0 \
  --workspace /var/horus/deployments

Options:

  • --port <PORT> - HTTP port (default: 8080)
  • --host <HOST> - Bind address (default: 0.0.0.0)
  • --workspace <DIR> - Deployment directory (default: /tmp/horus/deployments)
  • --max-deployments <N> - Max concurrent deployments (default: 5)
  • --log-level <LEVEL> - debug, info, warn, error (default: info)

Running as Service

systemd service (/etc/systemd/system/horus-daemon.service):

[Unit]
Description=HORUS Deployment Daemon
After=network.target

[Service]
Type=simple
User=horus
Group=horus
WorkingDirectory=/var/horus
ExecStart=/home/horus/.cargo/bin/horus_daemon --port 8080
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable horus-daemon
sudo systemctl start horus-daemon
sudo systemctl status horus-daemon

View logs:

sudo journalctl -u horus-daemon -f

Security Configuration

Firewall:

# Allow daemon port
sudo ufw allow 8080/tcp

# Or restrict to specific IP
sudo ufw allow from 192.168.1.0/24 to any port 8080

Authentication (recommended for production):

horus_daemon \
  --port 8080 \
  --auth-token "your-secret-token-here"

Deploy with authentication:

horus run --remote robot:8080 --auth-token "your-secret-token-here"

Deployment Workflow

Basic Deployment

# Deploy to robot
horus run --remote 192.168.1.100:8080

Output:

Preparing deployment...
   Packaged project (245 KB)
   Uploaded to 192.168.1.100:8080
   Building on robot (release mode)

Build output:
   Compiling horus_core v0.1.0
   Compiling my_robot_controller v1.0.0
    Finished release [optimized] target(s) in 23.45s

   Build successful
   Starting execution

Robot logs:
[12:34:56.789] Registered node 'VelocityController' with priority 5
[12:34:56.790] Registered node 'MotorDriver' with priority 10
[12:34:56.791] Scheduler started
[12:34:56.792] [IPC: 296ns] VelocityController --PUB--> 'cmd_vel' = 1.5
[12:34:56.793] [IPC: 420ns] MotorDriver <--SUB-- 'cmd_vel' = 1.5

Press Ctrl+C to stop...

Release vs Debug

Debug (fast compile, slow execution):

horus run --remote robot:8080

Release (slow compile, fast execution):

horus run --remote robot:8080 --release

Recommendation: Always use --release for real robot testing.

Specific File

# Deploy specific file
horus run --remote robot:8080 examples/demo.rs --release

With Arguments

# Pass arguments to your program
horus run --remote robot:8080 --release -- --config robot.yaml

Build Only

# Build on robot but don't run
horus run --remote robot:8080 --build-only --release

Managing Deployments

List Active Deployments

# Query daemon
curl http://192.168.1.100:8080/deployments

Response:

{
  "deployments": [
    {
      "id": "deploy_abc123",
      "status": "running",
      "pid": 12345,
      "started_at": "2025-10-09T14:30:00Z",
      "project": "my_robot_controller",
      "release": true
    }
  ]
}

Stop Deployment

# Stop specific deployment
curl -X POST http://192.168.1.100:8080/stop/deploy_abc123

Or use Ctrl+C in the terminal where you ran horus run --remote

View Deployment Logs

# Get logs for specific deployment
curl http://192.168.1.100:8080/logs/deploy_abc123

Fleet Management

Deploy to Multiple Robots

Shell script:

#!/bin/bash
ROBOTS=(
    "192.168.1.100:8080"
    "192.168.1.101:8080"
    "192.168.1.102:8080"
)

for robot in "${ROBOTS[@]}"; do
    echo "Deploying to $robot..."
    horus run --remote $robot --release &
done

wait
echo "All deployments complete"

Monitoring Multiple Robots

Dashboard integration:

# Robot 1
horus_daemon --port 8080 --dashboard-url http://monitor:3000

# Robot 2
horus_daemon --port 8080 --dashboard-url http://monitor:3000

# Central monitor
horus dashboard --port 3000

Rolling Updates

Zero-downtime deployment:

#!/bin/bash
ROBOTS=("robot1:8080" "robot2:8080" "robot3:8080")

for robot in "${ROBOTS[@]}"; do
    echo "Updating $robot..."

    # Deploy new version
    horus run --remote $robot --release &
    pid=$!

    # Wait for startup
    sleep 5

    # Verify health
    if curl -f http://$robot/health; then
        echo " $robot updated successfully"
    else
        echo " $robot update failed"
        kill $pid
    fi
done

Advanced Features

Custom Build Environment

Robot-side configuration:

horus_daemon \
  --port 8080 \
  --rust-version nightly \
  --target armv7-unknown-linux-gnueabihf

Persistent Deployments

Run as background service:

horus run --remote robot:8080 --release --daemon

Output:

Deployment started as daemon
  ID: deploy_abc123
  PID: 12345

Monitor with:
  curl http://robot:8080/logs/deploy_abc123

Stop with:
  curl -X POST http://robot:8080/stop/deploy_abc123

Environment Variables

Pass environment variables:

horus run --remote robot:8080 --release \
  --env RUST_LOG=debug \
  --env ROBOT_ID=robot_01

Custom Deployment Directory

On robot:

horus_daemon --workspace /opt/robot/deployments

Persistent across reboots:

horus_daemon --workspace /var/lib/horus --no-cleanup

Daemon API

Endpoints

POST /deploy

Upload and deploy a project.

Request:

tar czf project.tar.gz .
curl -X POST \
  -H "Content-Type: application/octet-stream" \
  --data-binary @project.tar.gz \
  http://robot:8080/deploy?release=true

Response:

{
  "deployment_id": "deploy_abc123",
  "status": "building",
  "message": "Deployment started"
}

GET /deployments

List all active deployments.

GET /deployment/:id

Get status of specific deployment.

Response:

{
  "id": "deploy_abc123",
  "status": "running",
  "pid": 12345,
  "started_at": "2025-10-09T14:30:00Z",
  "project": "my_robot_controller",
  "release": true,
  "uptime_seconds": 3600
}

POST /stop/:id

Stop a running deployment.

GET /logs/:id

Get logs for deployment.

Parameters:

  • tail=100 - Last N lines
  • follow=true - Stream logs

GET /health

Daemon health check.

Response:

{
  "status": "healthy",
  "version": "0.1.0",
  "uptime_seconds": 86400,
  "active_deployments": 2,
  "cpu_usage": 15.3,
  "memory_usage_mb": 245
}

Network Configuration

Finding Robot IP

On robot:

# Get all IPs
ip addr show

# Or just WiFi
ip addr show wlan0 | grep inet

# Or hostname
hostname -I

Common patterns:

  • WiFi: 192.168.1.x
  • Ethernet: 192.168.0.x
  • Hotspot: 10.0.0.x

Ubuntu/Debian (/etc/netplan/01-netcfg.yaml):

network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      addresses:
        - 192.168.1.100/24
      gateway4: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]

Apply:

sudo netplan apply

SSH Tunneling

For robots behind NAT:

# On dev machine
ssh -L 8080:localhost:8080 robot@robot-hostname

# Then deploy to localhost
horus run --remote localhost:8080

VPN

For remote access:

# Connect to VPN
sudo openvpn --config robot-network.ovpn

# Deploy through VPN
horus run --remote 10.8.0.100:8080

Cross-Compilation

Build for ARM on x86

Install target:

rustup target add armv7-unknown-linux-gnueabihf

Configure daemon:

horus_daemon --target armv7-unknown-linux-gnueabihf

Deploy:

horus run --remote robot:8080 --release

Supported Architectures

  • x86_64-unknown-linux-gnu - Intel/AMD 64-bit
  • aarch64-unknown-linux-gnu - ARM 64-bit (Raspberry Pi 4)
  • armv7-unknown-linux-gnueabihf - ARM 32-bit (Raspberry Pi 3)
  • arm-unknown-linux-gnueabi - ARM soft-float

Troubleshooting

Connection Refused

Error:

Error: Connection refused to 192.168.1.100:8080

Causes:

  • Daemon not running
  • Wrong IP or port
  • Firewall blocking
  • Robot offline

Solutions:

# Check daemon status on robot
systemctl status horus-daemon

# Check port
sudo lsof -i :8080

# Test connectivity
ping 192.168.1.100
telnet 192.168.1.100 8080

# Check firewall
sudo ufw status
sudo ufw allow 8080/tcp

Build Failed on Robot

Error:

Error: Build failed on robot
  error: could not compile `my_project`

Causes:

  • Missing dependencies
  • Wrong Rust version
  • Insufficient memory
  • Disk full

Solutions:

# Check daemon logs on robot
journalctl -u horus-daemon -n 50

# Check disk space
df -h

# Check memory
free -h

# Install dependencies
sudo apt update && sudo apt install \
  build-essential \
  pkg-config \
  libudev-dev \
  libssl-dev \
  libasound2-dev

# Increase swap (if low memory)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Deployment Timeout

Error:

Error: Deployment timeout
  No response from robot after 5 minutes

Solutions:

# Increase timeout
horus run --remote robot:8080 --timeout 600

# Check build progress
curl http://robot:8080/deployment/deploy_abc123

# Check logs
curl http://robot:8080/logs/deploy_abc123

Permission Denied

Error:

Error: Permission denied
  Cannot write to deployment directory

Solution on robot:

# Fix permissions
sudo chown -R horus:horus /var/horus/deployments
sudo chmod 755 /var/horus/deployments

Best Practices

Development Workflow

Local testing first:

# 1. Test locally
horus run --release

# 2. If works, deploy to robot
horus run --remote robot:8080 --release

Deployment Checklist

  • Test locally first
  • Use --release for real testing
  • Verify network connectivity
  • Check daemon is running
  • Monitor logs during deployment
  • Test robot behavior after deployment
  • Keep backup of working version

Monitoring

Keep dashboard running:

# On dev machine
horus dashboard

# Deploy to robot
horus run --remote robot:8080 --release

# Dashboard shows remote execution

Version Control

Tag releases:

git tag v1.0.0
git push origin v1.0.0

# Deploy tagged version
git checkout v1.0.0
horus run --remote robot:8080 --release

Next Steps