#micro-vm #artificial-intelligence #orchestration #docker #virtualization #isolation #groups #container #linux #agent

bin+lib monocore

monocore is a secure MicroVM provisioning system for running untrusted code in isolated environments

3 unstable releases

0.2.1 Dec 11, 2024
0.2.0 Dec 10, 2024
0.1.0 Dec 4, 2024

#168 in Unix APIs

Download history 47/week @ 2024-12-13 1/week @ 2025-01-03 2/week @ 2025-01-10

92 downloads per month

Apache-2.0

510KB
8K SLoC

monocore logo

monocore

Discord Build Status Monocore Crate Monocore Docs License

monocore is the engine behind the monocore platform, providing a robust foundation for running AI workloads in isolated microVMs. It handles everything from VM lifecycle management to OCI image distribution, making it easy to deploy and orchestrate code sandboxes securely.

Warning

This project is in early development and is not yet ready for production use.

Table of Contents

Overview

When developing AI agents that execute code, you need a fast development cycle:

  • Docker containers? Limited isolation for untrusted code
  • Traditional VMs? Minutes to start up, heavy resource usage
  • Direct execution? Risky for your development machine
  • Cloud sandboxes? Great for production, but slow for rapid iteration

monocore provides:

  • 🔒 True VM-level isolation
  • ⚡ Millisecond startup times
  • 🎯 Simple REST API
  • 📦 Works with standard container images
  • 🔧 Full resource control
  • 💻 Perfect for local development

Library Usage

Basic MicroVM

use monocore::vm::MicroVm;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Build the MicroVm
    let vm = MicroVm::builder()
        .root_path("/path/to/rootfs")  // Path to rootfs
        .ram_mib(512)
        .exec_path("/bin/true")  // Simple no-op command
        .build()?;

    // Start the MicroVm
    tracing::info!("Starting MicroVm...");
    vm.start()?;
    Ok(())
}

Service Orchestration

use monocore::{
    config::{Group, Monocore, Service},
    orchestration::Orchestrator,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Create a simple service
    let service = Service::builder_default()
        .name("app")
        .base("alpine:latest")
        .ram(512)
        .group("main")  // Group name is required
        .command("/bin/sleep")  // Example command
        .args(["infinity"])     // Run indefinitely
        .build();

    // Create the main group
    let main_group = Group::builder()
        .name("main")
        .build();

    let config = Monocore::builder()
        .services(vec![service])
        .groups(vec![main_group])
        .build()?;

    // Create orchestrator with log retention
    let mut orchestrator = Orchestrator::with_log_retention_policy(
        "/path/to/oci_dir",
        "/path/to/supervisor",
        LogRetentionPolicy::with_max_age_weeks(1),
    ).await?;

    // Start the service
    orchestrator.up(config).await?;

    Ok(())
}

Getting Started

Installation

Quick Install:

curl -sSfL https://install.monocore.dev | sh

This will install both the monocore command and its alias mc.

System Requirements:

Linux
  • KVM-enabled Linux kernel (check with ls /dev/kvm)
  • User must be in the kvm group (add with sudo usermod -aG kvm $USER)
macOS
  • Apple Silicon (ARM64) only
  • macOS 10.15 (Catalina) or later for Hypervisor.framework support
Windows

Coming soon!

Manual Build:

# Clone the repository
git clone https://github.com/appcypher/monocore.git
cd monocore

# Build and install (installs to /usr/local/bin)
make monocore && sudo make install

Basic Usage

  1. Create a configuration file:
# monocore.toml
[[service]]
name = "sh-counter"
base = "alpine:latest"
ram = 256
cpus = 1
group = "demo"
command = "/bin/sh"
args = ["-c", "for i in $(seq 1 10); do echo $i; sleep 2; done"]

[[service]]
name = "python-counter"
base = "python:3.11-slim"
ram = 256
cpus = 1
group = "demo"
command = "/usr/local/bin/python3"
args = [
    "-c",
    "import time; count=0; [print(f'Count: {count+1}') or time.sleep(2) or (count:=count+1) for _ in range(10)]",
]

[[group]]
name = "demo"
local_only = true
  1. Manage your services:
# Start services
monocore up -f monocore.toml

# View status
monocore status

# Stop services
monocore down

# Remove services
monocore remove -g main
  1. Run in server mode:
# Start the REST API server (default port: 3456)
monocore serve --port 3456

# Or use the default port
monocore serve

For more CLI options:

monocore --help

Configuration Schema

The monocore.toml configuration file supports the following structure:

# Service Definition
[[service]]
name = "service-name"          # Required: Name of the service
base = "image:tag"             # Optional: Base OCI image to use
group = "group-name"           # Optional: Group this service belongs to
command = "/path/to/binary"    # Optional: Command to run
args = ["arg1", "arg2"]        # Optional: Arguments for the command
cpus = 1                       # Optional: Number of vCPUs (default: 1)
ram = 1024                     # Optional: RAM in MiB (default: 1024)
workdir = "/app"               # Optional: Working directory
port = "8080:80"               # Optional: Port mapping (host:guest)
volumes = ["/host:/guest"]     # Optional: Volume mappings
envs = ["KEY=value"]           # Optional: Environment variables
depends_on = ["other-service"] # Optional: Service dependencies
group_envs = ["prod"]          # Optional: Environment variables for the group
group_volumes = [              # Optional: Volume mappings for the group
  {
    name = "shared-data",      # Required: Name of the volume
    path = "/data:/data"       # Required: Path mapping (host:guest)
  }
]

# Group Definition
[[group]]
name = "group-name"            # Required: Name of the group
local_only = true              # Optional: Restrict connection to local network (default: true)

# Group volume definition
[[group.volume]]
name = "shared-data"           # Required: Name of the volume
path = "/data"                 # Required: Base path on host system

# Group environment variables
[[group.env]]
name = "prod"                  # Required: Name of the environment group
envs = ["API_KEY=value"]       # Optional: Environment variables

Volume Mappings

Volumes can be specified in two formats:

  • Single path (/data): Uses the same path on both host and guest
  • Path pair (/host:/guest): Maps host path to a different guest path

Port Mappings

Ports can be specified in two formats:

  • Single port (8080): Uses the same port on both host and guest
  • Port pair (8080:80): Maps host port to a different guest port

Service Groups

Services can be organized into groups for:

  • Shared volume definitions
  • Common environment variables
  • Network isolation (when local_only = true)
  • Resource management

Dependencies

  • Services can specify dependencies using depends_on
  • Maximum dependency chain length is 32
  • Services are started in dependency order

REST API

When running in server mode, monocore provides a REST API for managing services:

Endpoint Method Description
/up POST Start services defined in config
/down POST Stop running services
/status GET Get status of all services
/remove POST Remove service files

Example API usage:

# Start services
curl -X POST http://localhost:3456/up \
  -H "Content-Type: application/json" \
  -d @monocore.json

# Get service status
curl http://localhost:3456/status

# Stop services in a group
curl -X POST http://localhost:3456/down \
  -H "Content-Type: application/json" \
  -d '{"group": "main"}'

# Remove services
curl -X POST http://localhost:3456/remove \
  -H "Content-Type: application/json" \
  -d '{"services": ["counter", "date-service"]}'

Features

Secure Isolation

  • Isolated microVM environments for each service
  • Resource constraints and limits enforcement
  • Network isolation between service groups
  • Perfect for running untrusted AI-generated code
  • Full system call isolation

Efficient Runtime

  • Fast microVM provisioning and startup
  • Millisecond-level boot times
  • Minimal resource overhead
  • Optimized layer caching and sharing
  • Memory-efficient design

OCI Integration

  • Pull images from any OCI-compliant registry
  • Smart layer management and deduplication
  • Local image caching for faster startups
  • Support for standard container images
  • Seamless Docker compatibility

Service Orchestration

  • Dependency-aware service scheduling
  • Health monitoring and automatic recovery
  • Log rotation with configurable retention
  • Resource usage tracking
  • Group-based service management

Architecture

Directory Structure

Monocore maintains its state in ~/.monocore:

graph TD
    monocore_root[~/.monocore] --> monoimage[monoimage/]
    monoimage --> monoimage_repo[repo/]
    monoimage_repo --> monoimage_cid["[repo-name]__[tag].cid"]
    monoimage --> monoimage_layer[layer/]

    monocore_root --> oci[oci/]
    oci --> oci_repo[repo/]
    oci_repo --> oci_tag["[repo-name]__[tag]/"]
    oci_tag --> oci_config[config.json]
    oci_tag --> oci_manifest[manifest.json]
    oci_tag --> oci_index[index.json]
    oci --> oci_layer[layer/]
    oci_layer --> oci_layer_hash["[hash]"]

    monocore_root --> rootfs[rootfs/]
    rootfs --> rootfs_service[service/]
    rootfs_service --> rootfs_service_rootfs["[service-name]/"]
    rootfs --> rootfs_ref[reference/]
    rootfs_ref --> rootfs_ref_repo["[repo-name]__[tag]/"]
    rootfs_ref_repo --> rootfs_ref_repo_merged[merged/]

    monocore_root --> service[service/]
    service --> service_info["[service-name]/"]
    service_info --> service_json[service.json]
    service_info --> group_json[group.json]

    monocore_root --> run[run/]
    run --> run_service["[service-name]__[pid].json"]

    monocore_root --> log[log/]
    log --> log_stderr["[service-name].stderr.log"]
    log --> log_stdout["[service-name].stdout.log"]

Development

For development setup and building from source, please visit the root of the project repository.

License

This project is licensed under the Apache License 2.0.

Dependencies

~31–69MB
~1M SLoC