GoShip is a Go-based, self-hosted VM-centric application control plane for project-scoped virtual machines built on the Linux virtualization stack.
Containers simplify application packaging, but virtual machines remain the strongest isolation boundary for multi-tenant systems, regulated workloads, and Confidential Computing.
GoShip is built around a simple model:
A project owns one or more virtual machines. All applications of that project execute inside those VMs via a project-scoped agent.
- VM-first isolation — Virtual machines are the unit of trust, security, and ownership
- Explicit virtualization — CPU topology, memory, devices, and firmware are first-class concepts
- Agent-mediated control — Applications are managed declaratively through an agent running inside the VM
- Upstream-aligned — Built directly on KVM, QEMU, and Libvirt
- Runtime-agnostic — Control plane remains unchanged across QEMU, Kata, Firecracker backends
- Confidential Computing-ready — Designed to support SEV-SNP, TDX, and attestation workflows
┌─────────────────────────────────────────────────────────┐
│ GoShip Control Plane │
│ (Projects, Apps, Nodes, Desired State) │
│ │
│ goship server (:8080) goship proxy (:8081) │
│ REST API Reverse Proxy │
│ (manage projects/apps) (route HTTP to VM apps) │
└───────────────────────────┬─────────────────────────────┘
│
Desired State
│
▼
┌─────────────────────────────────────────────────────────┐
│ Node (Linux Host) │
│ GoShip Agent │
└───────────────────────────┬─────────────────────────────┘
│
VM Lifecycle Management
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Project VM │ │ Project VM │ │ Project VM │
│ (Alpha) │ │ (Beta) │ │ (Gamma) │
├───────────────┤ ├───────────────┤ ├───────────────┤
│ GoShip Init │ │ GoShip Init │ │ GoShip Init │
├───────────────┤ ├───────────────┤ ├───────────────┤
│ ┌─────────┐ │ │ ┌─────────┐ │ │ ┌─────────┐ │
│ │Container│ │ │ │Container│ │ │ │ Process │ │
│ │ App A │ │ │ │ App X │ │ │ │ App P │ │
│ └─────────┘ │ │ └─────────┘ │ │ └─────────┘ │
│ ┌─────────┐ │ │ ┌─────────┐ │ └───────────────┘
│ │Container│ │ │ │Container│ │
│ │ App B │ │ │ │ App Y │ │
│ └─────────┘ │ │ └─────────┘ │
└───────────────┘ └───────────────┘
- Project lifecycle — Create, start, stop, restart, delete project VMs
- Container apps — Deploy Docker containers inside VMs with port mapping, env vars, and resource limits
- Process apps — Deploy binaries directly with auto-restart, exponential backoff, and per-process log files
- Binary upload — Transparent chunked transfer of local binaries into VMs over virtio-serial
- Local image deploy —
--local-imageflag exports a host Docker image, compresses it, and pushes it into the VM before deploying - Compose build support — Services with
build:in docker-compose.yml are built locally and pushed into VMs automatically viacompose up - Image management — Pull base Alpine cloud images, build local images, push images into VMs (
app push-image) - VM resource editing — Resize CPU, memory, and disk on stopped VMs without recreating the project
- App editing — Modify app specs (ports, env, image, resources) without redeploying
- Boot progress streaming — Real-time cloud-init log output during project creation
- Portable builds —
libvirt_dlopenbuild tag removes compile-time libvirt version dependency - KVM/TCG fallback — Automatic detection of KVM; graceful fallback to QEMU software emulation
- Auto network setup — Ensures the libvirt
defaultnetwork is active before VM creation - DAC security labels — Numeric UID/GID labels for precise QEMU file access control
- Environment variables — Project-level env vars inherited by all apps, with AES-256-GCM vault encryption for secrets
- REST API server —
goship serverserves a JSON API for project and app management - Smart API mode — CLI auto-detects a running server; use
--directto force direct libvirt mode - Reverse proxy — Domain-based HTTP routing to apps inside VMs, with automatic route lifecycle management
- Node management — Register, list, inspect, drain, and remove cluster nodes
# Install latest release (includes system dependencies)
curl -fsSL https://raw.githubusercontent.com/guilhermebr/goship/main/scripts/install.sh | bash
# Install specific version
curl -fsSL https://raw.githubusercontent.com/guilhermebr/goship/main/scripts/install.sh | GOSHIP_VERSION=v0.1.0 bash
# Skip system deps if already installed
curl -fsSL https://raw.githubusercontent.com/guilhermebr/goship/main/scripts/install.sh | GOSHIP_SKIP_DEPS=true bashOr build from source:
make build
sudo make install# Download base VM image
goship image pull
# Start the server (recommended — enables API mode + reverse proxy)
goship server &
# Create a project (provisions a VM with Docker)
goship project create myapp --cpu 1 --memory 512
# Set project-level environment variables (inherited by all apps)
goship env set myapp APP_ENV=production LOG_LEVEL=info
goship env set myapp DB_PASSWORD=s3cret --secret
goship env list myapp
# Assign domains for reverse proxy routing
goship domain set myapp myapp.local
goship domain list myapp
# Deploy a container app (inherits project env vars)
# After deploy, accessible at web.myapp.local:8081 via reverse proxy
goship app create myapp web --image nginx:alpine --port 8080:80
goship app deploy myapp web
# Deploy using a locally built Docker image (pushed into VM automatically)
goship app create myapp api --image myapi:latest --port 3000:3000
goship app deploy myapp api --local-image
# Deploy a process-mode app (binary uploaded into VM automatically)
goship app create myapp worker --mode process --binary ./bin/myworker --restart-policy on-failure
goship app deploy myapp worker
# Check status and logs
goship app list myapp
goship app logs myapp web
goship app logs myapp worker --follow
# Deploy multi-service apps with docker-compose.yml
# Services with build: are built locally and pushed into the VM
goship compose up myapp -f docker-compose.yml
goship compose ps myapp
goship compose down myapp
# Resize VM resources (must stop first)
goship project stop myapp
goship project edit myapp --cpu 2 --memory 1024 --disk 8192
goship project start myapp
# Edit an app and redeploy
goship app edit myapp web --port 9090:80
goship app deploy myapp web
# Use direct libvirt mode (skip server)
goship --direct project list
# Use explicit remote server
GOSHIP_API_URL=http://remote:8080 goship project list
# Clean up
goship app delete myapp web
goship app delete myapp worker
goship project delete myappSee the Getting Started guide for the full walkthrough.
| Document | Description |
|---|---|
| Getting Started | Install GoShip and deploy your first app |
| Concepts | How GoShip works — projects, apps, VMs, architecture |
| CLI Reference | Every command, flag, and example |
| Troubleshooting | Common problems and fixes |
| Design Document | Full architecture RFC |
| Decision Log | Architectural decisions and their rationale |
- Linux (KVM recommended; QEMU TCG software emulation used as fallback when
/dev/kvmis unavailable) - Go 1.26+ (install via mise:
make setupormise install) - System packages:
libvirt-dev,qemu-system-x86,qemu-utils,genisoimage,libguestfs-tools - User in the
libvirtgroup
GoShip values:
- Small, reviewable changes
- Clear documentation
- Explicit trade-offs
- Upstream-first thinking
Apache 2.0
This project exists thanks to the Linux virtualization community and the decades of work behind KVM, QEMU, Libvirt, and the Linux kernel.