Skip to content

nutcas3/omni

Repository files navigation

Omni

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                           │
│                                                         │
└─────────────────────────────────────────────────────────┘

Why Omni?

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

Installation

Prerequisites

  • Go 1.22+ - Install Go
  • Make - Usually pre-installed on macOS/Linux
  • UPX (optional but recommended) - For binary compression
  • Git - For version control

Option 1: From Source (Recommended for Development)

# 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

Option 2: Install UPX for Maximum Compression

# 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

First Run

# Initialize Omni
omni init

# You should see:
# ✓ Omni initialized successfully
#   Config: /home/user/.omni
#   Database: /home/user/.omni/omni.db

Quick Start

1. Setup Cloud Provider

For Hetzner Cloud (Easiest)

# 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

For Azure

# 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

2. Provision Your First Server

# 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: running

3. Deploy the Ghost Agent

The 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'

4. Deploy Your Application

# 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

5. Check Status

# 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 page

6. List All Deployments

omni list

# Output:
# NAME        PROVIDER   IP              IMAGE          STATUS
# ──────────────────────────────────────────────────────────────
# web-prod    hetzner    95.217.xxx.xxx  nginx:alpine   deployed

7. Destroy When Done

omni destroy web-prod

# Output:
# Destroying 'web-prod' on hetzner...
# ✓ Server destroyed successfully

Architecture

┌─────────────────────────────────────────────────────────┐
│                    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)                   │       │
│  └─────────────────────────────────────────────┘       │
└─────────────────────────────────────────────────────────┘

Binary Size Optimization Techniques

  1. CGO-Free Build - Enables static linking and cross-compilation
  2. Linker Flags - -ldflags="-s -w" strips symbols, reducing size by 20-40%
  3. UPX Compression - LZMA compression reduces size by 50-70%
  4. Minimal Dependencies - Raw HTTP for cloud APIs instead of massive SDKs

Cloud Provider Implementation

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

State Management

Why SQLite?

  • Local-first: No external database required
  • Embedded: Single file, easy backups
  • ACID: Transaction guarantees
  • Pure Go: modernc.org/sqlite has no CGO

SSH Dispatcher

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

Commands

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

Sovereign Sizes

  • micro → 1-2 vCPU, 1-2GB RAM
  • small → 2 vCPU, 2-4GB RAM
  • medium → 2-4 vCPU, 4-16GB RAM
  • large → 4-8 vCPU, 8-32GB RAM

Build Commands

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)

Project Structure

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

Development

Project Statistics

  • 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

Adding a New Cloud Provider

  1. Implement the Provider interface in internal/cloud/:
type NewCloudProvider struct {
    // Your fields
}

func (p *NewCloudProvider) CreateServer(ctx context.Context, opts ServerOptions) (*Instance, error) {
    // Implementation
}
// ... other methods
  1. Register in init():
func init() {
    RegisterProvider("newcloud", NewNewCloudProvider)
}
  1. Add size mapping to GetComputeMap() in provider.go

File Size Rules

  • All files must be <200 lines
  • Split large files into logical modules
  • Keep functions focused and small
  • Verify with: wc -l internal/**/*.go

CI/CD Integration

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 }}

Multi-Cloud Strategy

# 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

Roadmap

  • 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.

Philosophy

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

Troubleshooting

"Package not found" errors

# Run setup script
./scripts/setup.sh github.com/yourname/omni

# Clear module cache
go clean -modcache

# Retry
go mod tidy

Binary too large

# 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

Build fails

# Check Go version (need 1.22+)
go version

# Update Go if needed
# Then try again
go mod tidy
make dev

SSH Connection Fails

# 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.pub

Contributing

Contributions welcome! Please see CONTRIBUTING.md for guidelines.

Key requirements:

  1. Binary size stays <10MB
  2. Zero CGO dependencies
  3. Tests pass
  4. Code follows Go conventions
  5. All files under 200 lines

License

MIT

Acknowledgments

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.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors