- VM Lifecycle: Create, start, stop, suspend, resume, and destroy KVM virtual machines with flavor-based resource templates
- Container Lifecycle: Run Docker containers alongside VMs with unified scheduling
- Block Storage: Persistent volumes with attach/detach and storage pool capacity tracking
- Virtual Networking: Tenant-isolated networks with automatic IPAM, security groups, and floating IPs
- Auth & Multi-tenancy: JWT authentication, role-based access control, per-tenant quotas, and full resource isolation
- Scheduling: Bin-packing scheduler with affinity/anti-affinity placement groups
- Auto-scaling: Policy-based automatic scale-up/down driven by cluster CPU metrics
- Server Consolidation: Migrate workloads off underutilized nodes to free capacity
- VM Snapshots: Point-in-time capture and restore of VM state
- Cluster Health: Graduated health states (healthy/degraded/suspect/dead) with background monitoring
- Observability: Prometheus
/metricsendpoint, audit event trail, and alerting system - Node Management: Automatic node registration and heartbeat-based health reporting
- Live Migration: Zero-downtime VM migration between nodes with capacity validation
- Web Dashboard: React/TypeScript UI with real-time WebSocket updates, resource charts, and migration controls
- TUI Dashboard: Terminal UI with live cluster overview, VM/container management, and keyboard navigation
- API Documentation: Interactive docs page with code examples for all 40+ endpoints
Sahab is a Rust workspace with five crates plus a React frontend:
| Crate | Role |
|---|---|
sahab-controller |
API server, scheduler, auto-scaler, WebSocket events, static dashboard serving |
sahab-node |
Node agent — registers with controller, sends heartbeats |
sahab-cli |
Command-line client for all platform operations |
sahab-tui |
Terminal dashboard — ratatui-based live cluster overview |
sahab-common |
Shared models and types across all crates |
sahab-frontend |
React 19 + TypeScript + Vite + Tailwind CSS + shadcn/ui web dashboard |
git clone https://github.com/Adel-Ayoub/Sahab
cd Sahab
cargo build --releaseBinaries are produced in target/release/:
sahab-controller— the API serversahab-node— the node agentsahab-cli— the CLI clientsahab-tui— the terminal dashboard
cd crates/sahab-frontend
bun install
bun run buildThe built files go to crates/sahab-frontend/dist/ and are served by the controller at /.
./target/release/sahab-controller
# Listens on 127.0.0.1:3000 by default
# Seeds admin user (admin/admin) on first runsahab-cli login --username admin --password admin# List available flavors
sahab-cli flavor list
# Upload a disk image
sahab-cli image upload --name ubuntu --file ubuntu.qcow2
# Create a VM
sahab-cli vm create --name web-1 --flavor m1.small --image <image-id>
# Create a container
sahab-cli container create --name redis --image redis:latest
# Create a virtual network
sahab-cli network create --name internal --cidr 10.0.1.0/24 --gateway 10.0.1.1host = "127.0.0.1"
port = 3000
database_path = "sahab.db"
jwt_secret = "change-me-in-production"
[[nodes]]
name = "node-1"
address = "192.168.1.10"
port = 3001
total_vcpus = 16
total_memory_mb = 65536
total_disk_gb = 500name = "node-1"
controller_url = "http://127.0.0.1:3000"
address = "192.168.1.10"
port = 3001
total_vcpus = 16
total_memory_mb = 65536
total_disk_gb = 500
heartbeat_interval_secs = 5The CLI reads the controller URL from ~/.sahab/config.toml and stores auth tokens at ~/.sahab/token.
controller_url = "http://127.0.0.1:3000"sahab-cli login --username admin --password admin
sahab-cli user create --username alice --password secret --role tenant
sahab-cli user list
sahab-cli quota get --tenant alice
sahab-cli quota set --tenant alice --vcpus 10 --memory 20480 --instances 5sahab-cli vm create --name app-1 --flavor m1.medium --image <image-id>
sahab-cli vm list
sahab-cli vm start <vm-id>
sahab-cli vm stop <vm-id>
sahab-cli vm suspend <vm-id>
sahab-cli vm resume <vm-id>
sahab-cli vm destroy <vm-id>sahab-cli container create --name nginx --image nginx:latest --vcpus 1 --memory 512
sahab-cli container list
sahab-cli container inspect <id>
sahab-cli container start <id>
sahab-cli container stop <id>
sahab-cli container logs <id>
sahab-cli container remove <id>sahab-cli volume create --name data-vol --size 50 --pool default
sahab-cli volume list
sahab-cli volume attach <volume-id> --vm <vm-id>
sahab-cli volume detach <volume-id>
sahab-cli volume delete <volume-id>
sahab-cli storage-pool listsahab-cli network create --name prod --cidr 10.0.0.0/24 --gateway 10.0.0.1
sahab-cli network list
sahab-cli network inspect <id>
sahab-cli network connect --network <id> --instance <id> --instance-type vm
sahab-cli network disconnect --network <id> --interface <iface-id>
sahab-cli network delete <id>sahab-cli security-group create --name web-sg --description "Web servers"
sahab-cli security-group list
sahab-cli security-group add-rule --sg <id> --direction ingress --protocol tcp --port-min 80 --port-max 80
sahab-cli security-group assign --sg <id> --instance <id> --instance-type vmsahab-cli floating-ip allocate
sahab-cli floating-ip list
sahab-cli floating-ip associate --fip <id> --instance <id> --instance-type vm
sahab-cli floating-ip disassociate <fip-id>
sahab-cli floating-ip release <fip-id># Create an anti-affinity group to spread VMs across nodes
sahab-cli placement-group create --name web-spread --policy anti_affinity
sahab-cli placement-group list
sahab-cli placement-group add-member --group <id> --instance <vm-id> --instance-type vm
sahab-cli placement-group list-members <id>
sahab-cli placement-group remove-member --group <id> --instance <vm-id>
sahab-cli placement-group delete <id>sahab-cli snapshot create --vm <vm-id> --name before-upgrade
sahab-cli snapshot list
sahab-cli snapshot restore --snapshot <id> --name restored-vm# Scale between 2-10 VMs: add when CPU > 80%, remove when < 20%
sahab-cli scaling-policy create --name web-pool --flavor m1.small --min 2 --max 10 \
--scale-up-cpu 80 --scale-down-cpu 20 --cooldown 300
sahab-cli scaling-policy list
sahab-cli scaling-policy delete <id># Migrate workloads off underutilized nodes (admin only)
sahab-cli consolidatesahab-cli node list
sahab-cli event list --limit 20
sahab-cli event list --resource-type vm --resource-id <id>
sahab-cli alert list
sahab-cli alert acknowledge <id>| Method | Path | Description |
|---|---|---|
POST |
/api/v1/auth/login |
Authenticate and receive JWT |
POST |
/api/v1/users |
Create user (admin) |
GET |
/api/v1/users |
List users (admin) |
GET/PUT |
/api/v1/quotas/{tenant} |
Get/set tenant quotas |
GET |
/api/v1/nodes |
List cluster nodes |
POST |
/api/v1/nodes/register |
Node self-registration |
POST |
/api/v1/nodes/heartbeat |
Node heartbeat |
GET/POST |
/api/v1/vms |
List/create VMs |
POST |
/api/v1/vms/{id}/{action} |
Start/stop/suspend/resume/destroy |
POST |
/api/v1/vms/{id}/snapshot |
Create VM snapshot |
GET/POST |
/api/v1/containers |
List/create containers |
GET |
/api/v1/containers/{id} |
Inspect container |
POST |
/api/v1/containers/{id}/{action} |
Start/stop |
DELETE |
/api/v1/containers/{id} |
Remove container |
GET |
/api/v1/containers/{id}/logs |
Container logs |
GET/POST |
/api/v1/volumes |
List/create volumes |
POST |
/api/v1/volumes/{id}/attach |
Attach to VM |
POST |
/api/v1/volumes/{id}/detach |
Detach from VM |
GET/POST |
/api/v1/networks |
List/create networks |
POST |
/api/v1/networks/{id}/connect |
Connect instance |
GET/POST |
/api/v1/security-groups |
List/create security groups |
GET/POST |
/api/v1/floating-ips |
List/allocate floating IPs |
GET/POST |
/api/v1/placement-groups |
List/create placement groups |
POST |
/api/v1/placement-groups/{id}/members |
Add member |
GET |
/api/v1/snapshots |
List snapshots |
POST |
/api/v1/snapshots/{id}/restore |
Restore VM from snapshot |
GET/POST |
/api/v1/scaling-policies |
List/create scaling policies |
POST |
/api/v1/cluster/consolidate |
Server consolidation (admin) |
GET |
/api/v1/events |
Audit event log |
GET |
/api/v1/alerts |
List alerts |
POST |
/api/v1/alerts/{id}/acknowledge |
Acknowledge alert |
GET |
/api/v1/flavors |
List flavors |
GET/POST |
/api/v1/images |
List/upload images |
GET |
/api/v1/health |
Health check |
POST |
/api/v1/vms/{id}/migrate |
Live migrate VM to another node |
GET |
/api/v1/ws?token=JWT |
WebSocket for real-time cluster events |
GET |
/metrics |
Prometheus metrics |
GET |
/swagger-ui |
OpenAPI/Swagger documentation |
Sahab/
├── crates/
│ ├── sahab-common/ # Shared models, types, state machines
│ │ └── src/
│ │ └── models.rs
│ ├── sahab-controller/ # API server + scheduler + auto-scaler
│ │ └── src/
│ │ ├── main.rs
│ │ ├── auth.rs # JWT, password hashing, Claims extractor
│ │ ├── audit.rs # Immutable audit event trail
│ │ ├── autoscaler.rs # Background policy evaluator
│ │ ├── config.rs
│ │ ├── db.rs # SQLite schema, migrations, seeds
│ │ ├── health.rs # Graduated health state checker
│ │ ├── scheduler.rs # Bin-pack + affinity-aware placement
│ │ └── routes/
│ │ ├── mod.rs
│ │ ├── auth_routes.rs
│ │ ├── nodes.rs
│ │ ├── vms.rs
│ │ ├── containers.rs
│ │ ├── flavors.rs
│ │ ├── images.rs
│ │ ├── volumes.rs
│ │ ├── networks.rs
│ │ ├── security_groups.rs
│ │ ├── floating_ips.rs
│ │ ├── placement_groups.rs
│ │ ├── snapshots.rs
│ │ ├── scaling.rs
│ │ ├── events.rs
│ │ ├── alerts.rs
│ │ └── metrics.rs
│ ├── sahab-node/ # Node agent
│ │ └── src/
│ │ ├── main.rs
│ │ └── config.rs
│ ├── sahab-cli/ # CLI client
│ │ └── src/
│ │ ├── main.rs
│ │ └── output.rs
│ ├── sahab-tui/ # Terminal dashboard
│ │ └── src/
│ │ ├── main.rs
│ │ ├── app.rs
│ │ └── ui.rs
│ └── sahab-frontend/ # Web dashboard (React + TypeScript)
│ ├── src/
│ │ ├── App.tsx
│ │ ├── pages/ # Landing, Login, Dashboard, VMs, Containers, Docs, Platform
│ │ ├── components/ # Layout, cards, tables, charts, UI primitives
│ │ ├── api/ # API client, react-query hooks, types
│ │ ├── auth/ # AuthContext, ProtectedRoute, LoginPage
│ │ └── hooks/ # useClusterWs, useMetricsHistory, useActiveSection
│ ├── package.json
│ └── vite.config.ts
├── Cargo.toml # Workspace root
└── README.md
Copyright 2026 Adel-Ayoub
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.