Configuration Reference
This page documents all configuration options available in Capsa.
Boot Configurations
LinuxDirectBoot
Boot a VM directly with a Linux kernel and initrd (fastest method).
rust,no_run
use capsa::{DiskImage};
let boot = LinuxDirectBoot::new("./kernel", "./initrd");
// Optionally with root disk
let boot = LinuxDirectBoot::new("./kernel", "./initrd")
.with_root_disk(DiskImage::new("disk.img"));| Field | Type | Description |
|---|---|---|
kernel | PathBuf | Path to Linux kernel (bzImage format) |
initrd | PathBuf | Path to initial ramdisk |
root_disk | Option<DiskImage> | Optional root disk |
UefiBoot
Boot via UEFI firmware (macOS only currently).
rust,no_run
use capsa::{ DiskImage};
let disk = DiskImage::new("disk.img");
let boot = UefiBoot::new(disk);
// With EFI variable store
let disk = DiskImage::new("disk.img");
let boot = UefiBoot::new(disk)
.with_efi_variable_store("efi_vars.bin");| Field | Type | Description |
|---|---|---|
disk | DiskImage | Boot disk image |
efi_variable_store | Option<PathBuf> | EFI variables path |
create_variable_store | bool | Create if missing |
VM Builder Methods
Resource Configuration
rust,no_run
let vm = capsa::vm(boot)
.cpus(4) // Number of vCPUs (default: 1)
.memory_mb(2048) // Memory in MB (default: 512)
.timeout(Duration::from_secs(60)) // Operation timeout
.build()
.await?;Console
rust,ignore
.console_enabled() // Enable serial console accessNetworking
rust,ignore
use capsa::{Network, VirtualNetwork, Gateway, NetworkInterface, NetworkPolicy};
// No networking (default)
.network(Network::None)?
// Platform-native NAT (macOS only)
.network(Network::Nat)?
// Virtual networking with defaults
let network = VirtualNetwork::new();
.network(&network)?
// Virtual networking with custom gateway and policy
let network = VirtualNetwork::with_gateway(
Gateway::new("192.168.100.0/24").unwrap()
.policy(policy).unwrap()
);
.network(&network)?
// Port forwarding (per-interface)
let network = VirtualNetwork::new();
.interface(NetworkInterface::new(&network).forward_tcp(8080, 80))?Shared Directories
rust,ignore
use capsa::AccessMode;
// Basic share
.share("/host/path", "tag", AccessMode::ReadOnly)
.share("/host/path", "tag", AccessMode::ReadWrite)
// Multiple shares
.share("./src", "src", AccessMode::ReadOnly)
.share("./out", "out", AccessMode::ReadWrite)VM Sockets (vsock)
rust,ignore
// Host listens, guest connects
.vsock_listen(1024)
.vsock_listen_at(1024, "/tmp/custom.sock")
// Host connects, guest listens
.vsock_connect(2049)
.vsock_connect_at(2049, "/tmp/custom.sock")Disks
rust,ignore
use capsa::{DiskImage, ImageFormat};
// Add disk (becomes /dev/vdb, vdc, etc.)
.disk(DiskImage::new("data.img"))
// Read-only disk
.disk(DiskImage::new("data.img").read_only())
// Explicit format
.disk(DiskImage::with_format("data.qcow2", ImageFormat::Qcow2))Kernel Command Line (Linux only)
rust,ignore
// Add arguments
.cmdline_arg("root", "/dev/vda")
.cmdline_arg("init", "/sbin/init")
// Add flags
.cmdline_flag("quiet")
.cmdline_flag("nosmp")
// Override entire command line
.cmdline_override("console=hvc0 root=/dev/vda")Network Configuration
UserNatConfig
rust,ignore
use capsa_core::{UserNatConfig, NetworkPolicy};
use std::net::Ipv4Addr;
let config = UserNatConfig {
subnet: "10.0.2.0/24".to_string(),
gateway: Ipv4Addr::new(10, 0, 2, 2),
dhcp_start: Ipv4Addr::new(10, 0, 2, 15),
dhcp_end: Ipv4Addr::new(10, 0, 2, 254),
policy: Some(NetworkPolicy::deny_all().allow_https()),
};Port forwarding is configured per-interface via NetworkInterface::forward_tcp / forward_udp, not on UserNatConfig. See the Networking section above.
NetworkPolicy
rust,ignore
use capsa_core::{NetworkPolicy, PolicyAction, MatchCriteria, DomainPattern};
use std::net::Ipv4Addr;
// Start with default action
let policy = NetworkPolicy::deny_all(); // or allow_all()
// Add rules (first match wins)
let policy = policy
.allow_dns() // UDP port 53
.allow_https() // TCP port 443
.allow_port(80) // Any protocol, port 80
.allow_ip(Ipv4Addr::new(8, 8, 8, 8)) // Specific IP
.allow_ip_range("10.0.0.0", 8) // IP range (CIDR)
.allow_domain("api.example.com") // Exact domain
.allow_domain("*.github.com") // Wildcard subdomain
.deny_domain("*.evil.com")
.rule(PolicyAction::Log, MatchCriteria::Any); // Custom ruleMatch Criteria
rust,ignore
use capsa_core::{MatchCriteria, DomainPattern, Protocol};
MatchCriteria::Any // Match all traffic
MatchCriteria::Ip(ip) // Single IP
MatchCriteria::IpRange { network, prefix } // CIDR range
MatchCriteria::Port(443) // Single port
MatchCriteria::PortRange { start, end } // Port range
MatchCriteria::Protocol(Protocol::Tcp) // TCP or UDP
MatchCriteria::Domain(DomainPattern::Exact("api.com".into()))
MatchCriteria::Domain(DomainPattern::Wildcard("*.github.com".into()))
MatchCriteria::All(vec![...]) // AND multiple criteriaDisk Configuration
DiskImage
rust,no_run
// Auto-detect format from extension
let disk = DiskImage::new("disk.img"); // Raw
let disk = DiskImage::new("disk.qcow2"); // QCOW2
// Explicit format
let disk = DiskImage::with_format("disk.raw", ImageFormat::Raw);
// Read-only
let disk = DiskImage::new("disk.img").read_only();| Format | Extension | Linux KVM | macOS |
|---|---|---|---|
| Raw | .img, .raw | Supported | Supported |
| QCOW2 | .qcow2 | Supported | Not Supported |
Vsock Configuration
VsockPortConfig
rust,no_run
// Listen mode (guest connects to host)
let config = VsockPortConfig::listen(1024, "/tmp/vsock.sock");
let config = VsockPortConfig::listen_auto(1024); // Auto-generated path
// Connect mode (host connects to guest)
let config = VsockPortConfig::connect(2049, "/tmp/vsock.sock");| Field | Type | Description |
|---|---|---|
port | u32 | vsock port number |
socket_path | PathBuf | Unix socket path on host |
connect | bool | true = host connects, false = host listens |
auto_cleanup | bool | Delete socket on VM stop |
VM Handle Methods
Lifecycle
rust,ignore
vm.start().await?; // Start VM (if not running)
vm.shutdown().await?; // Graceful shutdown (30s timeout, then kills)
vm.kill().await?; // Force terminate
vm.wait().await?; // Wait for exit
vm.wait_timeout(Duration::from_secs(60)).await?;Status
rust,ignore
let status = vm.status();
match status {
VmStatus::Created => {},
VmStatus::Starting => {},
VmStatus::Running => {},
VmStatus::Stopping => {},
VmStatus::Stopped { exit_code } => {},
VmStatus::Failed { message } => {},
}Access
rust,ignore
let console = vm.console().await?; // Get console (requires console_enabled)
let socket = vm.vsock_socket(1024); // Get vsock by port
let sockets = vm.vsock_sockets(); // Get all vsocks
let resources = vm.resources(); // Get ResourceConfig
let os = vm.guest_os(); // Get GuestOsConsole Methods
The console provides raw serial port access. For command execution, use the agent instead.
Reading
rust,ignore
console.wait_for("pattern", Duration::from_secs(10)).await?;
console.read_available().await?;Writing
rust,ignore
console.write(b"raw bytes").await?;
console.write_line("with newline").await?;Control
rust,ignore
console.send_interrupt().await?; // Ctrl+C
console.send_eof().await?; // Ctrl+DSplitting
rust,ignore
let (reader, writer) = console.into_split().await?;
// reader: impl AsyncRead
// writer: impl AsyncWritePool Configuration
rust,ignore
let pool = capsa::vm_pool(boot)
.cpus(2)
.memory_mb(512)
.console_enabled()
.build(4) // Create 4 pre-warmed VMs
.await?;
let vm = pool.reserve().await?; // Wait for available
let vm = pool.try_reserve()?; // Non-blocking
let count = pool.available_count().await;Sandbox Pool Configuration
rust,ignore
let pool = capsa::sandbox_pool()
.cpus(2)
.memory_mb(512)
.share("./workspace", "/mnt/ws", AccessMode::ReadWrite)
.build(4) // Create 4 pre-warmed sandboxes
.await?;
let sandbox = pool.reserve().await?;
let agent = sandbox.agent().await?; // Get agent client
let result = agent.exec("echo").arg("hi").run().await?;Sandbox Configuration
rust,ignore
let network = VirtualNetwork::new();
let vm = capsa::sandbox()
.cpus(2)
.memory_mb(512)
.share("./workspace", "/mnt/ws", AccessMode::ReadWrite)
.network(&network)?
// OR .oci("python:3.11", &["python", "script.py"])
.build()
.await?;Agent Client
rust,ignore
let agent = vm.agent().await?;
agent.ping().await?;
let result = agent.exec("ls").arg("-la").run().await?;
let data = agent.read_file("/path").await?;
agent.write_file("/path", b"content").await?;
let exists = agent.exists("/path").await?;
let entries = agent.list_dir("/path").await?;
let info = agent.info().await?;