A lightweight private cloud platform for managing VMs on bare-metal Linux using KVM/Libvirt and Terraform
Quick Start β’ Features β’ Documentation β’ Architecture
Ghost Cloud transforms any Linux machine into a private cloud platform, providing AWS-like VM management through a simple CLI. Built on battle-tested technologies (KVM, Libvirt, Terraform), it offers:
- EC2-style instance flavors (12 pre-defined sizes across 4 series: nano, compute, memory, cpu)
- Pre-configured templates (nginx, docker, nodejs, python, postgresql, blank)
- Multi-environment support (dev, staging, prod with isolated configurations)
- Real-time monitoring dashboard (TUI with CPU, memory, disk I/O metrics)
- Infrastructure as Code with Terraform (declarative, version-controlled)
- Cloud-init automation (60-second VM provisioning from bare metal)
- SSH key injection (passwordless access via virt-customize)
Perfect for homelabs, development environments, CI/CD runners, Kubernetes clusters, or small-scale production workloads (10-50 VMs).
- No Dependencies on Cloud Providers: Run completely on-premises with full data control
- Cost-Effective: Zero cloud costs, leverage existing hardware
- Production-Ready: Battle-tested KVM/QEMU stack used by major cloud providers
- Developer-Friendly: Single-command VM creation, consistent environments
- GitOps Compatible: All infrastructure state tracked in Terraform
| Feature | Ghost Cloud | Proxmox VE | OpenStack | VMware ESXi |
|---|---|---|---|---|
| Setup Time | 5 minutes | 30 minutes | 2-4 hours | 1-2 hours |
| Learning Curve | Easy | Moderate | Steep | Moderate |
| Resource Overhead | Minimal | Low | High | Moderate |
| CLI-First | β Yes | β No | β No | |
| Infrastructure as Code | β Terraform | β Heat/Terraform | ||
| Cost | Free | Free | Free | Commercial |
| Multi-Environment | β Built-in | Manual | Manual | Manual |
| Best For | DevOps, Homelabs | General Purpose | Enterprise | Enterprise |
- Firewall: UFW enabled on template VMs (nginx, docker)
- SSH: Key-based authentication (password disabled after
inject-key) - Sudo:
ubuntuuser has NOPASSWD sudo (change in production) - Updates: Automatic security updates via
unattended-upgrades - Isolation: VMs isolated via NAT (no direct internet exposure)
# Inside VM
sudo passwd ubuntu# After SSH key injection
sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart sshd# Inside VM
sudo apt install fail2ban
sudo systemctl enable fail2ban# Enable AppArmor profiles
sudo aa-enforce /etc/apparmor.d/*# Create isolated network for sensitive VMs
virsh net-define isolated-net.xml
virsh net-start isolated-net- Data Residency: Full control over data location (on-premises)
- Audit Logs: All operations logged to
data/logs/cloud.log - Encryption: LUKS disk encryption for VM volumes (manual setup)
- Backup Compliance: Daily/weekly backups to off-site storage
Problem: Developers need isolated, reproducible environments
Solution: Spin up fresh VMs with specific stacks in 60 seconds
# Full-stack development environment
./ghost create dev-backend --flavor compute.medium --template nodejs
./ghost create dev-database --flavor memory.medium --template postgresql
./ghost create dev-cache --flavor memory.small --template blankProblem: GitHub Actions/Jenkins agents are expensive at scale
Solution: Self-hosted ephemeral runners on Ghost Cloud
# Create 5 CI runners
for i in {1..5}; do
./ghost create ci-runner-$i --flavor cpu.medium --template docker
doneProblem: Learning cloud technologies requires expensive subscriptions
Solution: Private cloud on old hardware
# Kubernetes learning environment
./ghost create k8s-master --flavor compute.large --template docker
./ghost create k8s-worker1 --flavor compute.medium --template docker
./ghost create k8s-worker2 --flavor compute.medium --template dockerProblem: Production-like environments are hard to maintain
Solution: Environment parity with Ghost Cloud
# Replicate production architecture
./ghost env staging
./ghost create staging-web --flavor compute.large --template nginx
./ghost create staging-api --flavor compute.medium --template nodejs
./ghost create staging-db --flavor memory.large --template postgresqlProblem: Running multiple services locally conflicts ports/resources
Solution: Isolated VMs per service
./ghost create auth-service --flavor nano.small --template nodejs
./ghost create payment-service --flavor nano.small --template python
./ghost create notification-service --flavor nano.small --template blank- Ubuntu 22.04+ (or Debian-based Linux)
- CPU with virtualization support (Intel VT-x / AMD-V)
- Minimum 8GB RAM, 50GB disk space
- Sudo access
# Clone the repository
git clone https://github.com/opskraken/kronos.git
cd kronos
# Run the bootstrap installer
./bootstrap/install.sh
# β οΈ IMPORTANT: Log out and log back in (required for group permissions)
# Verify installation
./ghost status# Create a web server VM
./ghost create web-1 --flavor compute.medium --template nginx
# Wait ~30 seconds for boot, then SSH in
./ghost ssh web-1
# Password: ubuntu
# Inject your SSH key for passwordless access
./ghost inject-key web-1
Creating a VM with Ghost Cloud - Simple one-line command
| Feature | Description |
|---|---|
| π₯οΈ Full VM Lifecycle | Create, start, stop, delete, clone VMs with single commands |
| π Real-time Dashboard | TUI monitoring with CPU%, memory%, disk I/O, network metrics (2s refresh) |
| ποΈ Instance Flavors | 12 pre-defined sizes from 512MB to 32GB RAM (AWS EC2-style) |
| π¦ Application Templates | Pre-configured nginx, docker, nodejs, python, postgresql with best practices |
| π Multi-Environment | Isolated dev/staging/prod with separate Terraform state management |
| π SSH Key Injection | Automated passwordless access via virt-customize (no manual key copying) |
| πΎ Backup & Restore | Snapshot creation, restore, and scheduled backup capabilities |
| π§ Infrastructure as Code | Fully managed by Terraform with JSON-based instance definitions |
| βοΈ Cloud-init Support | Industry-standard VM initialization (60s boot time) |
| π Hot Operations | Live disk resize, SSH key injection without VM recreation |
- Parallel VM Creation: Batch create multiple VMs simultaneously
- Interactive Wizard: Step-by-step VM creation with validation
- IP Auto-Discovery: Automatic DHCP lease tracking via virsh/Terraform
- Template Extensibility: Add custom templates in
templates/directory - Logging & Auditing: All operations logged to
data/logs/cloud.log - Host CPU Passthrough: Near-native performance with KVM acceleration
- Network Isolation: Support for multiple virtual networks (NAT, bridged)
- State Management: Terraform state backup and disaster recovery
# VM Lifecycle
./ghost create <name> # Create VM (interactive mode)
./ghost create <name> --flavor <f> --template <t> # Create with options
./ghost list # List all VMs
./ghost start <name> # Start a stopped VM
./ghost stop <name> # Stop a running VM
./ghost delete <name> # Permanently delete VM
# Access & Management
./ghost ssh <name> # SSH into VM (password: ubuntu)
./ghost inject-key <name> # Inject SSH key for passwordless access
./ghost monitor # Real-time resource dashboard
# Configuration
./ghost env # Show current environment
./ghost env <name> # Switch environment (dev/staging/prod)
./ghost flavors # List available instance sizes
./ghost templates # List available templates
./ghost status # System health check
# Help
./ghost help # Show all commands
./ghost version # Show versionList Running VMs
View all running instances with IP addresses and status
Real-time Monitoring Dashboard
Terminal-based dashboard showing CPU, memory, disk I/O metrics
| Series | Flavor | vCPU | RAM | Disk | Use Case |
|---|---|---|---|---|---|
| Burstable | nano.micro |
1 | 512MB | 10GB | Minimal workloads |
nano.small |
1 | 1GB | 20GB | Development, testing | |
nano.medium |
2 | 2GB | 30GB | Small production apps | |
| Compute | compute.small |
2 | 4GB | 40GB | General purpose |
compute.medium |
4 | 8GB | 80GB | Web servers, APIs | |
compute.large |
8 | 16GB | 160GB | Large applications | |
| Memory | memory.medium |
2 | 8GB | 40GB | Databases, caching |
memory.large |
4 | 16GB | 80GB | Redis, Memcached | |
memory.xlarge |
8 | 32GB | 160GB | In-memory databases | |
| CPU | cpu.medium |
4 | 4GB | 60GB | Compute workloads |
cpu.large |
8 | 8GB | 120GB | Video encoding, ML |
| Template | Description | Includes |
|---|---|---|
blank |
Basic Ubuntu | curl, wget, git, vim, htop |
nginx |
Web Server | Nginx, Certbot, UFW configured |
docker |
Container Runtime | Docker CE, Docker Compose, BuildX |
nodejs |
Node.js Dev | Node.js 20.x, npm, pm2, yarn, TypeScript |
python |
Python Dev | Python 3, pip, venv, Flask, Django, FastAPI |
postgresql |
Database | PostgreSQL 14+, pre-configured user/db |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β User Interface β
β ./ghost CLI (Bash) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Library Layer β
β lib/common.sh β lib/terraform.sh β lib/interactive.sh β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Infrastructure Layer β
β Terraform + Libvirt Provider β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Virtualization Layer β
β Libvirtd β QEMU/KVM β Linux Kernel β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Hardware Layer β
β CPU (VT-x/AMD-V) β RAM β Storage β Network β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ghost-cloud/
βββ ghost # Main CLI entry point (v1.1.0)
βββ flavors.yaml # Instance size definitions
βββ bootstrap/ # One-time installation scripts
β βββ install.sh # Main installer
β βββ install-kvm.sh # KVM/QEMU/Libvirt packages
β βββ configure-libvirt.sh # Network & storage setup
β βββ fix-permissions.sh # User group permissions
β βββ fix-apparmor.sh # Security profile fixes
βββ terraform/ # Infrastructure as Code
β βββ main.tf # Root configuration
β βββ variables.tf # Input definitions
β βββ outputs.tf # Output values
β βββ modules/
β βββ instance/ # VM creation module
β β βββ main.tf
β β βββ cloud-init.yaml
β βββ network/ # Network module
βββ environments/ # Per-environment configs
β βββ dev/
β βββ staging/
β βββ prod/
βββ templates/ # VM bootstrap scripts
β βββ blank.sh
β βββ nginx.sh
β βββ docker.sh
β βββ nodejs.sh
β βββ python.sh
β βββ postgresql.sh
βββ scripts/ # Operational scripts
β βββ backup/ # Backup & restore
β βββ monitoring/ # Dashboard & health checks
β βββ maintenance/ # Cleanup, resize, clone
βββ lib/ # Shared bash libraries
β βββ common.sh # Colors, logging, utilities
β βββ terraform.sh # Terraform helpers
β βββ interactive.sh # Interactive menu wizard
βββ docs/ # Documentation
βββ runbooks/ # Operational guides
| Document | Description |
|---|---|
| Quick Start | Getting started guide |
| Architecture | System design details |
| Flavors Guide | Instance sizing guide |
| Templates Guide | Template customization |
| Troubleshooting | Common issues & fixes |
| Backup & Restore | Data protection |
| Networking | Network configuration |
| Scaling | Capacity planning |
ghost createβ Updatesenvironments/<env>/instances.auto.tfvars.jsonwith VM specs- Terraform β Reads config, calls libvirt provider to provision resources
- Libvirt Provider β Creates qcow2 volume, cloud-init ISO, and KVM domain
- QEMU/KVM β Boots VM with hardware acceleration (VT-x/AMD-V)
- Cloud-Init β Sets hostname, user, password, runs template script (nginx, docker, etc.)
- DHCP β Assigns IP from
192.168.122.0/24range via libvirt's dnsmasq ghost sshβ Connects via virsh IP lookup or Terraform state output
CLI Input β Flavor YAML Parsing β Terraform JSON Generation β
Libvirt Resource Creation β Cloud-init Execution β DHCP Lease β
Template Script Run β SSH Key Injection β Ready State- Base Image: Ubuntu 22.04 cloud image (shared, read-only)
- VM Disks: Copy-on-write qcow2 volumes (thin-provisioned)
- Cloud-init: ISO9660 disk for first-boot configuration
- Storage Pool:
/var/lib/libvirt/images/(default pool)
- Default Network:
virbr0bridge with NAT (192.168.122.0/24) - Gateway: Host machine at
192.168.122.1 - DHCP: Managed by libvirt's built-in dnsmasq server
- Port Forwarding: Optional via iptables rules (manual setup)
| User | Password | Sudo Access | SSH Key Auth |
|---|---|---|---|
ubuntu |
ubuntu |
NOPASSWD:ALL | After ghost inject-key |
Security Note: Password authentication is enabled by default for initial setup. Use ghost inject-key <vm-name> immediately after first login to enable passwordless SSH and disable password auth.
Symptom: terraform apply fails with "Could not open '/var/lib/libvirt/images/ubuntu-22.04-base.qcow2': Permission denied"
Root Cause: Terraform creates VM disk files owned by root, but QEMU runs as libvirt-qemu user and cannot access them.
Solution:
# Complete fix (run all commands):
sudo chown -R libvirt-qemu:kvm /var/lib/libvirt/images/
sudo ./bootstrap/fix-permissions.sh
sudo ./bootstrap/fix-apparmor.sh
sudo systemctl restart libvirtd
# If VM already exists in broken state:
virsh undefine <vm-name>
# Retry creation:
./ghost create <vm-name> --flavor <flavor> --template <template>Prevention: The updated ghost script now automatically fixes permissions after VM creation.
Symptom: terraform apply errors
Solution:
# Check if libvirt is running
sudo systemctl status libvirtd
# Verify user permissions
groups | grep libvirt # Should show 'libvirt' group
# Re-initialize Terraform
cd terraform && rm -rf .terraform && terraform initSymptom: Cannot SSH into VM after creation
Solution:
# Wait 30-60 seconds for boot
sleep 30
# Check VM is running
virsh list --all
# Verify IP assignment
virsh domifaddr <vm-name>
# Test connectivity
ping $(virsh domifaddr <vm-name> | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}')Symptom: VM creation fails with disk errors
Solution:
# Check available space
df -h /var/lib/libvirt/images/
# Clean up old VMs
./ghost list
./ghost delete <unused-vm>
# Prune unused volumes
virsh vol-list default
virsh vol-delete --pool default <volume-name>Symptom: virsh commands fail
Solution:
# Fix permissions
sudo ./bootstrap/fix-permissions.sh
# Fix AppArmor (if needed)
sudo ./bootstrap/fix-apparmor.sh
# Log out and log back in# Allocate 2GB huge pages
echo 1024 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# Make permanent
echo "vm.nr_hugepages = 1024" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p# Edit VM XML
virsh edit <vm-name>
# Add CPU pinning
<cputune>
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='1'/>
</cputune># Use SSD for VM images
sudo mkdir /mnt/ssd-vms
sudo virsh pool-create-as ssd-pool dir --target /mnt/ssd-vms
# Enable discard/TRIM
virsh edit <vm-name>
# Add: <driver name='qemu' type='qcow2' discard='unmap'/># Enable verbose logging
export LIBVIRT_DEBUG=1
# Check cloud-init logs inside VM
./ghost ssh <vm-name>
sudo cat /var/log/cloud-init-output.log
sudo journalctl -u cloud-initFor more detailed troubleshooting, see docs/runbooks/troubleshooting.md.
Installed automatically by bootstrap/install.sh:
| Package | Purpose | Version |
|---|---|---|
qemu-kvm |
Hardware-accelerated virtualization | Latest |
libvirt-daemon-system |
VM management daemon | 8.0+ |
libvirt-clients |
virsh CLI tools |
8.0+ |
virtinst |
virt-install VM creation utility |
Latest |
bridge-utils |
Virtual network bridges | Latest |
libguestfs-tools |
virt-customize for SSH key injection |
Latest |
terraform |
Infrastructure as Code engine | β₯1.0 |
jq |
JSON processing for instance configs | Latest |
yq |
YAML processing (optional, enhances flavor parsing) | Latest |
| Component | Minimum | Recommended |
|---|---|---|
| CPU | Intel VT-x / AMD-V | 4+ cores with passthrough |
| RAM | 8GB | 16GB+ (host + VM overhead) |
| Disk | 50GB free | 200GB+ SSD |
| OS | Ubuntu 22.04+ | Ubuntu 24.04 LTS |
| Network | 1 Gbps NIC | 10 Gbps for multiple VMs |
- VM Boot Time: 30-60 seconds (from create to SSH-ready)
- Disk I/O: 90% of native with virtio drivers
- CPU Performance: 95-98% native with host-passthrough
- Network Throughput: 940 Mbps on 1 Gbps link (virtio-net)
Core VM Management
- Full VM lifecycle management (create, start, stop, delete, clone)
- 12 instance flavors across 4 series (burstable, compute, memory, cpu)
- 6 pre-configured templates with best practices
- Multi-environment support (dev/staging/prod with isolated state)
- Real-time TUI monitoring dashboard with refresh rate control
- SSH key injection via
virt-customize(automated workflow)
Infrastructure & Automation
- Cloud-init based provisioning (60-second boot times)
- Terraform state management with automatic backups
- JSON-based instance configuration (GitOps-ready)
- Flavor definitions via YAML (easy customization)
- Interactive VM creation wizard (user-friendly CLI)
Operations & Monitoring
- Comprehensive logging (
data/logs/cloud.log) - Health check command (
ghost status) - VM resource monitoring (CPU, memory, disk, network)
- IP address auto-discovery (virsh + Terraform)
- Error handling and validation (flavor/template checks)
Documentation & Testing
- Complete documentation (README, guides, runbooks)
- Architecture diagrams and technical guides
- Troubleshooting runbooks
- Quick start guide and examples
Phase 1: Enhanced Operations (Q1 2025)
- Scheduled automatic backups with retention policies (daily/weekly/monthly)
- Terraform state backup automation to S3/MinIO
- VM tagging and labels (cost tracking, team ownership)
- Resource quotas per environment (prevent over-provisioning)
Phase 2: Advanced Networking (Q2 2025)
- Custom isolated networks with VLAN support
- Simple load balancing (HAProxy/nginx integration)
- Port forwarding configuration via CLI
- DNS management for VMs (custom domains)
Phase 3: Monitoring & Observability (Q3 2025)
- Web-based dashboard (real-time metrics)
- Prometheus metrics export
- Grafana dashboard templates
- Alerting via email/Slack/webhook
Phase 4: Multi-Node & HA (Q4 2025)
- Multi-host support (distributed VMs)
- Shared storage with Ceph/NFS
- VM migration between hosts
- High availability for critical VMs
| Metric | Value |
|---|---|
| Lines of Code | ~2,500 (Bash + Terraform + YAML) |
| Supported Templates | 6 (nginx, docker, nodejs, python, postgresql, blank) |
| Instance Flavors | 12 (512MB - 32GB RAM) |
| Documentation Pages | 10+ (guides, runbooks, architecture) |
| Average VM Creation Time | 45 seconds |
| Tested VM Count | 1-50 VMs per host |
Contributions are welcome! This project follows industry best practices and clean code principles.
-
Fork the repository
git clone https://github.com/yourusername/ghost-cloud.git
-
Create a feature branch
git checkout -b feature/amazing-feature
-
Make your changes
- Add tests for new features
- Update documentation
- Follow existing code style (shellcheck for bash)
-
Test your changes
./ghost create test-vm --flavor nano.small --template blank ./ghost delete test-vm
-
Commit with descriptive messages
git commit -m 'feat: Add custom network support for VMs' -
Push to your fork
git push origin feature/amazing-feature
-
Open a Pull Request
- Describe your changes
- Link related issues
- Add screenshots for UI changes
- Bash Scripts: Follow Google Shell Style Guide
- Terraform: Use
terraform fmtbefore committing - Documentation: Update README.md and relevant docs
- Commit Messages: Follow Conventional Commits
- π Additional template scripts (Redis, MongoDB, Kubernetes, etc.)
- π Web-based dashboard implementation
- π§ͺ Automated testing framework
- π Multi-language support for CLI
- π± Mobile-friendly monitoring interface
This project is licensed under the MIT License - see the LICENSE file for details.
- Terraform Libvirt Provider by dmacvicar - Core infrastructure provider
- Ubuntu Cloud Images - Optimized base images for cloud-init
- KVM/QEMU and Libvirt communities - Virtualization foundation
- Cloud-init project - Industry-standard VM initialization
- HashiCorp Terraform - Infrastructure as Code framework
- AWS EC2: Instance flavor naming and sizing methodology
- OpenStack: Multi-environment architecture patterns
- Vagrant: Simple CLI for complex operations
- Proxmox VE: Dashboard and monitoring approach
Built with β€οΈ for DevOps Engineers, SREs, and Homelab Enthusiasts
Made with β€οΈ for the homelab community