Qube lets you run isolated Linux containers from a single Go binary. It provides a Docker-like workflow for pulling images, starting containers, exposing ports, mounting volumes, passing environment variables, snapshotting containers, and executing commands inside running workloads.
Qube can be used from:
- a CLI for local development and systems experiments
- a daemon that monitors and restarts managed containers
- a REST API and WebSocket interface for programmatic container management
- a
qube.ymlconfig file for repeatable container launches
Status: Qube is an educational and experimental container runtime. It demonstrates Linux namespaces, cgroups v2, filesystem isolation, daemon supervision, and image-based workflows. It is not a drop-in replacement for Docker or containerd.
- Qube
- Lightweight Linux container runtime written in Go
- Linux namespace isolation for PID, mount, network, IPC, and UTS namespaces
- cgroups v2 support for CPU and memory resource controls
- Docker-like CLI workflow
- Background daemon for monitoring and restarting containers
- REST API for container lifecycle operations
- WebSocket support for interactive command execution
- Image pulling from Qube Hub
- Port mapping, volumes, and environment variable support
qube.ymlconfiguration for repeatable launches- Snapshot support for container state
- Desktop and hub subprojects for UI and image distribution workflows
flowchart TD
User["User"]
subgraph ControlPlane["Host Control Plane"]
CLI["Command-Line Interface"]
Daemon["Background Daemon"]
APIClient["API Client"]
end
subgraph Runtime["Qube Runtime"]
Core["Container Runtime Engine"]
API["Management API<br/><small>REST + WebSocket</small>"]
Lifecycle["Container Lifecycle Tracker"]
end
subgraph Isolation["Isolated Container Environment"]
Namespaces["Namespace Isolation"]
Cgroups["Resource Limits<br/><small>cgroups v2</small>"]
Filesystem["Isolated Root Filesystem"]
end
subgraph Storage["Storage Layer"]
Images["Image Store<br/><small>Qube Hub tarballs</small>"]
State["Container State Database"]
end
User --> CLI
CLI --> Core
CLI --> APIClient
APIClient --> API
API --> Core
Daemon --> Lifecycle
Daemon --> Core
Core --> Namespaces
Core --> Cgroups
Core --> Filesystem
Core --> Images
Lifecycle --> State
| Path | Purpose |
|---|---|
main.go |
Entrypoint and CLI dispatch |
src/cli/ |
CLI commands such as run, list, stop, pull, eval, snapshot, info, and delete |
src/daemon/ |
Background monitor that restarts containers and cleans orphaned state |
src/api/ |
REST API on 127.0.0.1:3030 and WebSocket execution endpoint |
src/core/container/ |
Runtime implementation: namespace setup, chroot, image extraction, filesystem operations, container startup |
src/core/cgroup/ |
cgroups v2 CPU and memory resource controls |
src/core/tracking/ |
Container tracking and persistence in /var/lib/Qube/containers.txt |
src/config/ |
Global paths and test path overrides |
src/testutil/ |
Helpers for remapping mutable paths in future tests |
qube-apps/desktop/ |
Electron desktop app |
qube-apps/hub/ |
Web hub for images and related workflows |
- Linux only
- Root privileges
- Go 1.21+ for building from source
- cgroups v2 for resource limits
tar,rsync, and build tools- systemd if installing the daemon service through
make install
Install common dependencies on Ubuntu/Debian:
sudo apt-get update
sudo apt-get install -y golang build-essential tar rsync makeCheck cgroups v2:
mount | grep cgroup2If cgroups v2 is unavailable, Qube can still run containers, but CPU and memory limits may not be applied.
git clone https://github.com/Voyrox/Qube
cd Qube
make installStart the daemon:
sudo systemctl start qubedPull and run a container:
sudo qube pull Voyrox:nodejs:25.2.0
sudo qube run --image Voyrox:nodejs:25.2.0 --ports 3000 --cmd "npm install && npm start"Inspect and stop the container:
sudo qube list
sudo qube info <container_name>
sudo qube stop <container_name>| Command | Description |
|---|---|
make build |
Build the qube binary |
make install |
Build, install the binary, set permissions, and install the systemd service |
make clean |
Remove build artifacts |
make deps |
Download and tidy Go dependencies |
make fmt |
Format Go code |
make lint |
Run golangci-lint if installed |
make test |
Run Go tests with coverage output |
make daemon |
Build and run sudo ./qube daemon --debug |
make dev |
Build with the Go race detector |
make release |
Cross-compile Linux AMD64 and ARM64 binaries into bin/ |
sudo qube run --image <image> --cmd "<command>"Examples:
# Run a Node.js service and expose port 3000
sudo qube run --image Voyrox:nodejs:25.2.0 --ports 3000 --cmd "node server.js"
# Run with environment variables
sudo qube run --image Voyrox:python:3.12.3 --env "DEBUG=true" --cmd "python app.py"
# Run with a volume mount
sudo qube run --image Voyrox:rust:1.92.0 --volume /host/path:/container/path --cmd "cargo run"
# Run with network isolation
sudo qube run --image Voyrox:nodejs:25.2.0 --ports 3000 --isolated --cmd "node server.js"sudo qube daemon # Start daemon manually
sudo qube run # Run container from flags or qube.yml
sudo qube list # List managed containers
sudo qube info <name> # Show container metadata
sudo qube start <name> # Start a stopped container
sudo qube stop <name> # Stop a running container
sudo qube delete <name> # Delete container state
sudo qube eval <name> # Execute command in a container
sudo qube snapshot <name> # Create a snapshot
sudo qube pull <image> # Pull image from Qube HubQube supports a qube.yml file for repeatable container launches. The CLI supports both a container: top-level shape and a flatter legacy shape.
container:
system: Voyrox:nodejs:25.2.0
ports:
- "3000"
cmd:
- npm install
- node index.js
isolated: false
environment:
API_KEY: "your-key-here"
NODE_ENV: "development"
volumes:
- host_path: "/data"
container_path: "/app/data"Run it:
sudo qube run| Field | Description |
|---|---|
system |
Image identifier to run |
ports |
Ports to expose |
cmd |
Command or command list executed inside the container |
isolated |
Whether to enable stronger network isolation |
environment |
Environment variables injected into the container |
volumes |
Host-to-container volume mappings |
Compatibility note: Some legacy structs preserve both
environmentand the misspelledenviromentfield. Preferenvironmentin new config files.
The API is served locally on 127.0.0.1:3030.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/list |
List containers |
POST |
/stop |
Stop a container |
POST |
/start |
Start a container |
POST |
/delete |
Delete a container |
POST |
/info |
Get container details |
GET |
/images |
List available images |
GET |
/volumes |
List volumes |
WS |
/eval/{name}/{action} |
Execute commands through WebSocket |
Example API call:
curl http://127.0.0.1:3030/listExample stop request:
curl -X POST http://127.0.0.1:3030/stop \
-H "Content-Type: application/json" \
-d '{"name":"Qube-example"}'Qube starts containers through a special init mode:
/proc/self/exe __container_init__
The runtime passes container setup through environment variables such as:
QUBE_ROOTFSQUBE_CMDQUBE_ISOLATEDQUBE_PIPE_FDQUBE_ARG_NQUBE_ENV_N
It then configures namespaces, filesystem isolation, and process startup.
The cgroup layer controls memory and CPU where supported. Current defaults include:
- memory limit: 2 GB
- swap limit: 1 GB
- CPU quota: 2 cores
Container state is persisted in:
/var/lib/Qube/containers.txt
The tracking file is pipe-delimited:
name|pid|dir|cmds|timestamp|image|ports|isolated
Container IDs are generated as:
Qube-<6 alphanumeric chars>
unless a specific name is provided.
The daemon checks containers periodically and restarts managed containers when appropriate. Crash-loop protection pauses restart attempts after repeated failures.
Run the project checks:
make fmt
make testGenerate a coverage profile:
go test -v -covermode=count -coverprofile=coverage.out ./...Current testing notes:
- The repository currently has the test command and CI flow wired up.
- The
src/testutilpackage provides helpers for remapping mutable global paths tot.TempDir(). - Add future tests as
_test.gofiles and use the path override helpers to avoid touching/var/lib/Qubeduring tests.
Recommended future test coverage:
qube.ymlparsing for both camelCase and snake_case keys- image name parsing and pull path generation
- tracking file read/write behavior
- daemon restart counter behavior
- cgroup file generation using a temporary root
- API handler tests with mocked runtime operations
Qube requires root privileges for namespace, mount, chroot, and cgroup operations.
sudo qube <command>Check for cgroups v2:
mount | grep cgroup2If there is no cgroup2 mount, containers can run without resource limits.
sudo systemctl status qubed
sudo systemctl start qubedOr run manually:
sudo qube daemon --debugsudo qube pull Voyrox:nodejs:25.2.0make clean
make deps
make build- Linux-only
- Root-only
- Requires cgroups v2 for resource limits
- Not a production security boundary
- Volumes and environment variables are not persisted in the tracking file
- No Windows support
- Some config shapes are preserved for legacy compatibility
- Container images are expected in Qube Hub tarball format
Qube is useful for learning and experimentation, but it should not be treated as a hardened sandbox. Running untrusted workloads as root can be dangerous. Review code paths, filesystem mounts, and image sources before running third-party workloads.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature- Format and test:
make fmt
make test- Commit:
git commit -m "Add my feature"- Push and open a pull request.
When adding runtime features, include:
- README updates
- config examples
- troubleshooting notes if the feature can fail due to kernel, permission, or cgroup behavior
- tests where possible
See LICENSE.
Qube is maintained by Voyrox and contributors.
