- Rust 59.3%
- JavaScript 15.8%
- HTML 12.6%
- Shell 11.7%
- Makefile 0.6%
| .forgejo/workflows | ||
| crates | ||
| docs/schemas | ||
| schemas/compute | ||
| scripts | ||
| sdk/js | ||
| src | ||
| templates | ||
| .gitignore | ||
| build.rs | ||
| buildenv.sh | ||
| Cargo.toml | ||
| COMPLETION_SUMMARY.md | ||
| IMPLEMENTATION_STATUS.md | ||
| Makefile | ||
| README.md | ||
| test_phase2.sh | ||
| test_phase4.sh | ||
| test_server.sh | ||
Hero Compute Manager
Per-user VM lifecycle management server for the Hero Ecosystem. Each user gets their own microVM with a unique mycelium IPv6 address. Uses chvm-lib as a Rust library for VM operations — no CLI shelling.
Architecture
┌─────────────────────────────────────────┐
│ Admin Dashboard (UI) │
│ Bootstrap 5.3 dark mode │
└──────────────────┬──────────────────────┘
│ JSON-RPC 2.0
┌──────────────────▼──────────────────────┐
│ Axum Web Server │
│ (POST /rpc + GET /) │
├─────────────────────────────────────────┤
│ UserVmManager │
│ Per-user VM lifecycle + Redis state │
├─────────────────────────────────────────┤
│ HypervisorDriver trait │
├──────────────┬──────────────────────────┤
│ MockDriver │ ChvmLibDriver │
│ (in-memory) │ (chvm-lib, Linux only) │
└──────────────┴──────────┬───────────────┘
│ Rust library
┌────────▼────────┐
│ chvm-lib │
│ Cloud Hypervisor│
│ + Mycelium │
└─────────────────┘
Driver Selection
| Platform | Driver | Behavior |
|---|---|---|
| Linux | ChvmLibDriver |
Real microVMs via chvm-lib with mycelium networking |
| macOS/other | MockDriver |
Fake VMs with mock mycelium IPs (fd00::N) for development |
Selection is automatic via #[cfg(target_os = "linux")] — no feature flags needed. On macOS, a warning is printed and MockDriver is used.
Per-User VM Model
Each user owns exactly one VM. UserVmManager tracks user → VM → mycelium IP mappings:
- In-memory:
RwLock<HashMap<String, UserVm>>for fast access - Redis:
user_vm:{user_id}→ UserVm JSON,mycelium_ip:{ip}→ user_id (reverse lookup) - Idle suspension: Background task suspends VMs idle longer than
IDLE_TIMEOUT_SECS
Users connect directly to their VM's mycelium IPv6 address — no host proxy in the data path.
Quick Start
Prerequisites
- Rust 1.75+
- Redis on
localhost:6379 - Linux with KVM for real VMs (macOS uses mock driver automatically)
Development (mock driver, TCP, any platform)
make run
# API: http://localhost:3389
# RPC: http://localhost:3389/api/root/compute/rpc
# UI: http://localhost:3389/
Or with live logs:
make dev
Development (Unix socket, like production)
HERO_COMPUTE_BIND=unix:/tmp/hero_compute_manager.sock make run
# API accessible via hero_proxy or: curl --unix-socket /tmp/hero_compute_manager.sock http://localhost/api/root/compute/rpc
Production (deployed by hero_zero)
hero_zero sets HERO_COMPUTE_BIND=unix:~/hero/var/sockets/hero_compute_manager.sock. The socket path is:
- Server socket:
~/hero/var/sockets/hero_compute_manager.sock(OpenRPC endpoint) - Port: 3389 (fallback TCP for development, not used in production)
hero_proxy routes /hero_compute_manager/* to this socket. The binary needs CAP_NET_ADMIN (set by hero_zero's first-run setup) for chvm-lib TAP/bridge management.
Sockets & Ports
| Component | Binding | Purpose |
|---|---|---|
| hero_compute_manager | ~/hero/var/sockets/hero_compute_manager.sock or 127.0.0.1:3389 |
OpenRPC 2.0 API + Admin UI |
Health Check
# TCP (development)
make health
# Unix socket (production)
make health-socket
Build & Test
make build # Release build
make check # Cargo check all targets
make test # Run all tests
make clippy # Lint with Clippy
make fmt # Format code (in-place)
make fmt-check # Check code formatting (no changes)
make release # Optimized release build
make dev # Development mode (faster compilation)
make run # Run release build on TCP
make run-socket # Run on Unix socket
make health # Health check on TCP
make health-socket # Health check on Unix socket
API
All operations use JSON-RPC 2.0 via POST /rpc.
VM Driver Methods
| Method | Description |
|---|---|
info |
Server info |
health |
Health check |
vm.list |
List all VMs |
vm.get |
Get VM by ID (params: { "vm_id": "..." }) |
vm.create |
Create VM |
vm.start |
Start a VM |
vm.stop |
Stop a VM |
vm.restart |
Restart a VM (stop + start) |
vm.delete |
Delete a VM |
vm.metrics.query |
Query time-series metrics |
User Management Methods
| Method | Description |
|---|---|
user.provision |
Create and start a VM for a user |
user.deprovision |
Stop and delete a user's VM |
user.vm |
Get a user's VM (includes mycelium IP) |
user.start |
Resume a suspended user VM |
user.stop |
Suspend a user's VM |
user.list |
List all user VMs |
Examples
Provision a user VM:
curl -X POST http://localhost:3760/rpc \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "user.provision",
"params": {
"user_id": "alice",
"name": "alice-vm",
"image": "alpine:latest",
"cpu_count": 2,
"memory_mb": 1024
}
}'
Response includes mycelium_ip — the user connects to this address directly via mycelium.
Get user's VM:
curl -X POST http://localhost:3760/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"user.vm","params":{"user_id":"alice"}}'
Resume a suspended VM:
curl -X POST http://localhost:3760/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"user.start","params":{"user_id":"alice"}}'
VM Data Model
{
"id": "a1b2c3d4e5f6",
"name": "alice-vm",
"state": "running",
"image": "alpine:latest",
"resources": {
"cpu_count": 2,
"memory_mb": 1024,
"disk_gb": 10
},
"mycelium_ip": "4ab:1234:5678:9abc::1",
"tap_device": "tap-abc12345",
"ip_address": "172.17.0.2/24",
"created_at": "2025-01-15T10:30:00Z",
"started_at": "2025-01-15T10:31:00Z",
"stopped_at": null
}
User VM Data Model
{
"user_id": "alice",
"vm_id": "a1b2c3d4e5f6",
"vm_name": "alice-vm",
"mycelium_ip": "4ab:1234:5678:9abc::1",
"state": "running",
"resources": { "cpu_count": 2, "memory_mb": 1024, "disk_gb": 10 },
"image": "alpine:latest",
"created_at": "2025-01-15T10:30:00Z",
"started_at": "2025-01-15T10:31:00Z",
"stopped_at": null,
"last_activity": "2025-01-15T11:00:00Z"
}
VM States
| State | Meaning |
|---|---|
created |
VM exists but hasn't been started |
running |
VM is actively running |
stopped |
VM has been stopped / suspended |
failed |
VM encountered an error |
Environment Variables
| Variable | Default | Description |
|---|---|---|
COMPUTE_HOST |
127.0.0.1 |
Server bind address |
COMPUTE_PORT |
3760 |
Server port |
REDIS_URL |
redis://localhost:6379 |
Redis connection |
CHVM_ENABLED |
false |
Enable chvm-lib driver (Linux only, falls back to mock on macOS) |
MYCELIUM_PEERS |
(empty) | Comma-separated mycelium peer addresses |
MYCELIUM_ENABLED |
true |
Enable mycelium networking for VMs |
IDLE_TIMEOUT_SECS |
300 |
Seconds before idle VM is suspended |
IDLE_CHECK_INTERVAL_SECS |
60 |
How often to check for idle VMs |
OAUTH_ENABLED |
false |
Enable OAuth2 JWT authentication |
OAUTH_REQUIRE_AUTH |
false |
Require auth for all requests |
OAUTH_JWKS_URL |
http://localhost:3350/.well-known/jwks.json |
JWKS endpoint |
OAUTH_ISSUER |
hero_auth |
Expected JWT issuer |
OAUTH_AUDIENCE |
hero-compute |
Expected JWT audience |
METRICS_INTERVAL_SECS |
5 |
Metrics collection interval |
RUST_LOG |
info,hero_compute=debug |
Log level filter |
Project Structure
hero_compute_manager/
├── Cargo.toml
├── Makefile
├── buildenv.sh
├── src/
│ ├── main.rs # Server entry, driver selection, RPC dispatch
│ ├── lib.rs # Library exports
│ ├── config.rs # Config with MyceliumConfig, IdleConfig
│ ├── state.rs # AppState with driver, user_manager, jwt
│ ├── rpc.rs # JSON-RPC types
│ ├── handlers.rs # Template handlers
│ ├── mcp.rs # MCP server integration
│ ├── api/
│ │ ├── vm.rs # VM CRUD handlers (delegates to driver)
│ │ ├── user.rs # User VM management handlers
│ │ ├── metrics.rs # Metrics query handler
│ │ ├── audit.rs # Audit log handler
│ │ └── info.rs # Server info
│ ├── vm/
│ │ ├── model.rs # Vm, VmState, VmResources (+ mycelium fields)
│ │ ├── driver.rs # HypervisorDriver trait
│ │ ├── lifecycle.rs # Start/stop/restart orchestration
│ │ └── mylist.rs # URI resolver
│ ├── drivers/
│ │ ├── mod.rs # Conditional compilation (Linux: chvm, all: mock)
│ │ ├── mock.rs # MockDriver (in-memory, fake mycelium IPs)
│ │ └── chvm.rs # ChvmLibDriver (chvm-lib, Linux only)
│ ├── user/
│ │ ├── mod.rs # Module declarations
│ │ ├── manager.rs # UserVm, UserVmManager (Redis + in-memory)
│ │ └── idle.rs # IdleChecker background task
│ ├── storage/ # Redis storage (metrics, events)
│ ├── metrics/ # Background metrics collector
│ └── auth/ # OAuth2 JWT authentication
└── templates/ # Askama HTML templates (dashboard)
Platform Support
- Linux:
ChvmLibDriverwith real chvm-lib. Binary needsCAP_NET_ADMIN(set during hero_zero first-run setup). - macOS/other:
MockDriverwith fake mycelium IPs (fd00::N). Logs a warning at startup. Full lifecycle testable without chvm or mycelium.
License
Apache-2.0