The Cloud-Agnostic Deployment Platform in <10MB
Omni is a sovereign minimalist deployment tool that combines the declarative power of Kubernetes-style control planes with the imperative speed of Kamal — all inside a single, statically-linked Go binary.
┌─────────────────────────────────────────────────────────┐
│ Omni: The <10MB Cloud-Agnostic Control Plane │
├─────────────────────────────────────────────────────────┤
│ │
│ ✓ Zero dependencies (static binary) │
│ ✓ Multi-cloud abstraction (Azure, Hetzner, AWS) │
│ ✓ SSH-based imperative deployment │
│ ✓ SQLite state management (no external DB) │
│ ✓ Container-native workflows │
│ ✓ CI/CD webhook integration │
│ │
└─────────────────────────────────────────────────────────┘
Binary Size Comparison:
- Kamal: ~10MB gem + ~30MB Ruby runtime = 40MB total
- Crossplane: Kubernetes cluster + operators = >500MB
- Omni: 5-8MB total (CLI + Agent)
Feature Comparison:
| Feature | Kamal | Crossplane | Omni |
|---|---|---|---|
| Binary Size | 40MB | 500MB+ | 5-8MB |
| Dependencies | Ruby, SSH | K8s, Helm | None |
| Multi-Cloud | Manual | Yes | Yes |
| Speed | Fast | Slow | Instant |
| State Storage | SSH | K8s etcd | SQLite |
- Go 1.22+ - Install Go
- Make - Usually pre-installed on macOS/Linux
- UPX (optional but recommended) - For binary compression
- Git - For version control
# Clone the repository
git clone https://github.com/nutcas3/omni.git
cd omni
# Download dependencies
go mod tidy
# Build the project
make build
# Verify binary size
make size-check
# Install to /usr/local/bin
sudo make install# macOS
brew install upx
# Ubuntu/Debian
sudo apt-get install upx-ucl
# Fedora/RHEL
sudo dnf install upx
# Then build with compression
make clean && make all# Initialize Omni
omni init
# You should see:
# ✓ Omni initialized successfully
# Config: /home/user/.omni
# Database: /home/user/.omni/omni.db# Get API token from https://console.hetzner.cloud/
export HETZNER_API_TOKEN="your-token-here"
# Test it works
omni up --name test --provider hetzner --size micro# Install Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Login
az login
# Set environment variables
export AZURE_SUBSCRIPTION_ID=$(az account show --query id -o tsv)
export AZURE_RESOURCE_GROUP="omni-rg"
export AZURE_TOKEN=$(az account get-access-token --query accessToken -o tsv)
# Create resource group
az group create --name omni-rg --location eastus
# Test it works
omni up --name test --provider azure --size small# Create a small server on Hetzner
omni up \
--name web-prod \
--provider hetzner \
--size small \
--region nbg1
# Output:
# Provisioning 'web-prod' on hetzner (cx21 in nbg1)...
# ✓ Server provisioned successfully
# ID: 12345678
# IP: 95.217.xxx.xxx
# Status: runningThe agent needs to be deployed to the server before you can deploy applications.
# SSH into the server
ssh omni@95.217.xxx.xxx
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker omni
exit
# From your local machine, upload and start the agent
# (This will be automated in a future release)
scp bin/omni-agent omni@95.217.xxx.xxx:/tmp/
ssh omni@95.217.xxx.xxx 'sudo mv /tmp/omni-agent /usr/local/bin/ && sudo chmod +x /usr/local/bin/omni-agent'
# Create systemd service
ssh omni@95.217.xxx.xxx 'sudo tee /etc/systemd/system/omni-agent.service' << 'EOF'
[Unit]
Description=Omni Ghost Agent
After=network.target docker.service
[Service]
Type=simple
User=omni
ExecStart=/usr/local/bin/omni-agent serve
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# Start the agent
ssh omni@95.217.xxx.xxx 'sudo systemctl daemon-reload && sudo systemctl enable omni-agent && sudo systemctl start omni-agent'# Deploy nginx
omni deploy \
--target web-prod \
--image nginx:alpine \
--port 80
# Output:
# Deploying nginx:alpine to web-prod...
# ✓ Deployment successful
# Container ID: abc123def456
# Status: running# Check deployment status
omni status web-prod
# Output:
# Deployment: web-prod
# Provider: hetzner
# Instance ID: 12345678
# IP Address: 95.217.xxx.xxx
# Image: nginx:alpine
# Status: deployed
# Created: 2024-01-15T10:30:00Z
# Updated: 2024-01-15T10:32:00Z
# Test the application
curl http://95.217.xxx.xxx
# You should see the nginx welcome pageomni list
# Output:
# NAME PROVIDER IP IMAGE STATUS
# ──────────────────────────────────────────────────────────────
# web-prod hetzner 95.217.xxx.xxx nginx:alpine deployedomni destroy web-prod
# Output:
# Destroying 'web-prod' on hetzner...
# ✓ Server destroyed successfully┌─────────────────────────────────────────────────────────┐
│ Omni CLI (5-8MB) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Cloud │ │ SSH │ │ SQLite │ │
│ │ Provider │ │Dispatcher│ │ State │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
│
│ SSH Connection
▼
┌─────────────────────────────────────────────────────────┐
│ Remote Server (Cloud VM) │
│ ┌─────────────────────────────────────────────┐ │
│ │ Ghost Agent (<2MB) │ │
│ │ - Container orchestration │ │
│ │ - Health checks │ │
│ │ - HTTP API (port 8080) │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
- CGO-Free Build - Enables static linking and cross-compilation
- Linker Flags -
-ldflags="-s -w"strips symbols, reducing size by 20-40% - UPX Compression - LZMA compression reduces size by 50-70%
- Minimal Dependencies - Raw HTTP for cloud APIs instead of massive SDKs
Instead of using bloated SDKs (AWS SDK v1: ~50MB, Azure SDK: ~100MB+), Omni uses raw HTTP REST calls for the essential API operations:
- CreateInstance
- GetInstance
- DeleteInstance
- ListInstances
Why SQLite?
- Local-first: No external database required
- Embedded: Single file, easy backups
- ACID: Transaction guarantees
- Pure Go:
modernc.org/sqlitehas no CGO
Native Go SSH implementation using golang.org/x/crypto/ssh:
- No external binary dependencies
- SCP protocol implementation for file transfer
- Remote command execution and streaming
| Command | Description |
|---|---|
omni init |
Initialize Omni |
omni up |
Provision server |
omni deploy |
Deploy container |
omni list |
List deployments |
omni status |
Show details |
omni destroy |
Terminate server |
omni version |
Show version |
omni --help |
Show help |
micro→ 1-2 vCPU, 1-2GB RAMsmall→ 2 vCPU, 2-4GB RAMmedium→ 2-4 vCPU, 4-16GB RAMlarge→ 4-8 vCPU, 8-32GB RAM
make build # Build binaries
make compress # Apply UPX compression
make install # Install to /usr/local/bin
make test # Run tests
make size-check # Verify binary size
make clean # Remove artifacts
make dev # Quick build (no compression)omni/
├── cmd/omni/ # CLI commands
├── internal/
│ ├── cloud/ # Cloud providers
│ ├── ssh/ # SSH dispatcher
│ ├── state/ # SQLite store
│ └── ui/ # Bubble Tea TUI
├── pkg/agent/ # Ghost agent
└── scripts/ # Build scripts
- 18 Go files - 2,319 total lines
- Largest file: 194 lines (pkg/agent/main.go)
- Average file: 129 lines
- 100% compliance with <200 line limit
- Binary target: <10MB compressed
- Implement the
Providerinterface ininternal/cloud/:
type NewCloudProvider struct {
// Your fields
}
func (p *NewCloudProvider) CreateServer(ctx context.Context, opts ServerOptions) (*Instance, error) {
// Implementation
}
// ... other methods- Register in
init():
func init() {
RegisterProvider("newcloud", NewNewCloudProvider)
}- Add size mapping to
GetComputeMap()inprovider.go
- All files must be <200 lines
- Split large files into logical modules
- Keep functions focused and small
- Verify with:
wc -l internal/**/*.go
Add to your GitHub Actions:
- name: Install Omni
run: curl -fsSL https://get.omni.io | sh
- name: Deploy
env:
HETZNER_API_TOKEN: ${{ secrets.HETZNER_TOKEN }}
run: |
omni deploy \
--target production \
--image ghcr.io/${{ github.repository }}:${{ github.sha }}# Primary on Hetzner (cheap)
omni up --name web-primary --provider hetzner --size small
# Failover on Azure (reliable)
omni up --name web-failover --provider azure --size small- AWS provider implementation
- DigitalOcean provider
- HTMX dashboard (embedded in binary)
- Webhook API for CI/CD
- Reconciliation loop (Kubernetes-style)
- Tailscale integration for private networking
- Multi-region deployments
- Auto-scaling policies
- Metrics and logging aggregation
See TODO.md for complete development roadmap.
Sovereign Minimalism
- No external dependencies
- Local-first state management
- Cloud vendor independence
- Binary size discipline
Imperative Speed
- SSH-based deployment
- Instant feedback
- No waiting for reconciliation loops
Production Ready
- Statically linked
- Cross-platform
- Battle-tested libraries
# Run setup script
./scripts/setup.sh github.com/yourname/omni
# Clear module cache
go clean -modcache
# Retry
go mod tidy# Install UPX
brew install upx # macOS
sudo apt-get install upx-ucl # Linux
# Rebuild with compression
make clean && make all
# Check dependencies
go mod graph# Check Go version (need 1.22+)
go version
# Update Go if needed
# Then try again
go mod tidy
make dev# Check SSH key exists
ls -la ~/.ssh/id_rsa
# Generate if missing
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# Specify custom key
omni up --name test --ssh-key ~/.ssh/custom_key.pubContributions welcome! Please see CONTRIBUTING.md for guidelines.
Key requirements:
- Binary size stays <10MB
- Zero CGO dependencies
- Tests pass
- Code follows Go conventions
- All files under 200 lines
MIT
Inspired by:
- Kamal - Imperative deployment philosophy
- Crossplane - Cloud provider abstraction
- Kubernetes - Control plane patterns
- SQLite - Embedded databases done right
Built with ❤️ and an obsession for minimal binaries.